diff --git a/.classpath b/.classpath
deleted file mode 100644
index eb19361..0000000
--- a/.classpath
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/.eslintrc.js b/.eslintrc.js
deleted file mode 100644
index 505a094..0000000
--- a/.eslintrc.js
+++ /dev/null
@@ -1,177 +0,0 @@
-module.exports = {
- extends: ['plugin:prettier/recommended'],
- plugins: ['prettier', '@typescript-eslint'],
- parser: '@typescript-eslint/parser',
- parserOptions: {
- createDefaultProgram: true,
- project: './tsconfig.json',
- },
- rules: {
- 'prettier/prettier': 'warn',
- '@typescript-eslint/adjacent-overload-signatures': 'error',
- '@typescript-eslint/array-type': 'error',
- '@typescript-eslint/await-thenable': 'error',
- '@typescript-eslint/ban-types': 'off',
- '@typescript-eslint/class-name-casing': 'off',
- '@typescript-eslint/consistent-type-assertions': 'error',
- '@typescript-eslint/consistent-type-definitions': 'error',
- '@typescript-eslint/explicit-member-accessibility': [
- 'off',
- {
- accessibility: 'explicit',
- },
- ],
- '@typescript-eslint/indent': [
- 'error',
- 4,
- {
- FunctionDeclaration: {
- parameters: 'first',
- },
- FunctionExpression: {
- parameters: 'first',
- },
- SwitchCase: 1,
- },
- ],
- '@typescript-eslint/interface-name-prefix': 'off',
- '@typescript-eslint/member-delimiter-style': 'error',
- '@typescript-eslint/member-ordering': 'off',
- '@typescript-eslint/no-empty-function': 'off',
- '@typescript-eslint/no-empty-interface': 'off',
- '@typescript-eslint/no-explicit-any': 'off',
- '@typescript-eslint/no-floating-promises': 'off',
- '@typescript-eslint/no-inferrable-types': 'off',
- '@typescript-eslint/no-misused-new': 'off',
- '@typescript-eslint/no-namespace': 'off',
- '@typescript-eslint/no-parameter-properties': 'off',
- '@typescript-eslint/no-require-imports': 'off',
- '@typescript-eslint/no-unnecessary-qualifier': 'error',
- '@typescript-eslint/no-unnecessary-type-assertion': 'error',
- '@typescript-eslint/no-use-before-declare': 'off',
- '@typescript-eslint/no-var-requires': 'off',
- '@typescript-eslint/prefer-for-of': 'off',
- '@typescript-eslint/prefer-function-type': 'error',
- '@typescript-eslint/prefer-namespace-keyword': 'error',
- '@typescript-eslint/quotes': [
- 'error',
- 'single',
- {
- avoidEscape: true,
- },
- ],
- '@typescript-eslint/semi': ['error'],
- '@typescript-eslint/space-within-parens': ['off', 'never'],
- '@typescript-eslint/triple-slash-reference': 'off',
- '@typescript-eslint/type-annotation-spacing': 'error',
- '@typescript-eslint/unified-signatures': 'error',
- 'arrow-body-style': 'error',
- 'arrow-parens': ['off', 'as-needed'],
- camelcase: 'off',
- 'capitalized-comments': 'off',
- complexity: 'off',
- 'constructor-super': 'error',
- curly: ['error', 'multi-line'],
- 'dot-notation': 'off',
- 'eol-last': 'error',
- eqeqeq: ['error', 'smart'],
- 'guard-for-in': 'off',
- 'id-blacklist': ['error', 'any', 'string', 'boolean', 'Undefined'],
- 'id-match': 'error',
- 'sort-imports': [
- 'error',
- {
- ignoreCase: false,
- ignoreDeclarationSort: true,
- ignoreMemberSort: false,
- memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
- },
- ],
- 'linebreak-style': 'off',
- 'max-classes-per-file': 'off',
- 'max-len': [
- 'off',
- {
- ignorePattern: '^import |^export {(.*?)}',
- code: 200,
- },
- ],
- 'new-parens': 'off',
- 'newline-per-chained-call': 'off',
- 'no-bitwise': 'off',
- 'no-caller': 'error',
- 'no-cond-assign': 'off',
- 'no-console': [
- 'off',
- {
- allow: [
- 'log',
- 'warn',
- 'dir',
- 'timeLog',
- 'assert',
- 'clear',
- 'count',
- 'countReset',
- 'group',
- 'groupEnd',
- 'table',
- 'debug',
- 'dirxml',
- 'error',
- 'groupCollapsed',
- 'Console',
- 'profile',
- 'profileEnd',
- 'timeStamp',
- 'context',
- ],
- },
- ],
- 'no-constant-condition': 'error',
- 'no-control-regex': 'off',
- 'no-debugger': 'error',
- 'no-duplicate-imports': 'error',
- 'no-empty': 'off',
- 'no-eval': 'off',
- 'no-extra-semi': 'off',
- 'no-fallthrough': 'error',
- 'no-invalid-regexp': 'error',
- 'no-invalid-this': 'off',
- 'no-irregular-whitespace': 'off',
- 'no-multiple-empty-lines': 'off',
- 'no-new-wrappers': 'error',
- 'no-redeclare': ['error', { builtinGlobals: false }],
- 'no-regex-spaces': 'error',
- 'no-return-await': 'error',
- 'no-shadow': [
- 'off',
- {
- hoist: 'all',
- },
- ],
- 'no-throw-literal': 'error',
- 'no-trailing-spaces': 'error',
- 'no-undef-init': 'error',
- 'no-underscore-dangle': 'off',
- 'no-unsafe-finally': 'error',
- 'no-unused-expressions': [
- 'error',
- {
- allowTaggedTemplates: true,
- allowShortCircuit: true,
- },
- ],
- 'no-unused-labels': 'error',
- 'no-var': 'error',
- 'object-shorthand': 'error',
- 'one-var': ['off', 'never'],
- 'prefer-arrow/prefer-arrow-functions': 'off',
- 'prefer-const': 'error',
- 'quote-props': 'off',
- radix: 'error',
- 'space-before-function-paren': 'off',
- 'use-isnan': 'error',
- 'valid-typeof': 'off',
- },
-};
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index bdb0cab..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1,17 +0,0 @@
-# Auto detect text files and perform LF normalization
-* text=auto
-
-# Custom for Visual Studio
-*.cs diff=csharp
-
-# Standard to msysgit
-*.doc diff=astextplain
-*.DOC diff=astextplain
-*.docx diff=astextplain
-*.DOCX diff=astextplain
-*.dot diff=astextplain
-*.DOT diff=astextplain
-*.pdf diff=astextplain
-*.PDF diff=astextplain
-*.rtf diff=astextplain
-*.RTF diff=astextplain
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..04d38ab
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: [farfromrefug]
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..edece08
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,112 @@
+name: 'release'
+
+on:
+ workflow_dispatch:
+ inputs:
+ release_type:
+ type: choice
+ default: auto
+ description: What kind of version upgrade
+ options:
+ - auto
+ - patch
+ - minor
+ - major
+
+jobs:
+ release:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: "0"
+ submodules: true
+
+ - name: setup node
+ uses: actions/setup-node@v4
+ with:
+ node-version: lts/*
+ registry-url: 'https://registry.npmjs.org'
+
+
+ - uses: oNaiPs/secrets-to-env-action@v1
+ with:
+ secrets: ${{ toJSON(secrets) }}
+
+
+ - uses: oleksiyrudenko/gha-git-credentials@v2-latest
+ with:
+ token: '${{ secrets.GITHUB_TOKEN }}'
+ name: Martin Guillon
+ email: dev@akylas.fr
+
+ - name: install jq
+ run: sudo apt install jq
+
+ - name: Enable CorePack
+ run: |
+ corepack enable
+ yarn config get globalFolder # the yarn command will ensure the correct yarn version is downloaded and installed
+
+ - name: Get yarn cache directory path
+ id: yarn-cache-dir-path
+ run: echo "::set-output name=dir::$(yarn config get globalFolder)"
+
+ - name: Remove package.json resolutions
+ run: echo "`jq 'delpaths([["resolutions"]])' package.json`" > package.json
+
+ - uses: actions/cache@v4
+ name: Handle node_modules Cache
+ id: yarn-node_modules # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
+ with:
+ path: node_modules
+ key: ${{ runner.os }}-yarn-node_modules-${{ hashFiles('**/yarn.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-node_modules-
+
+ - uses: actions/cache@v4
+ if: steps.yarn-node_modules.outputs.cache-hit != 'true'
+ name: Handle Yarn cache
+ id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
+ with:
+ path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
+ key: ${{ runner.os }}-yarn-cache-${{ hashFiles('**/yarn.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-yarn-
+
+ - name: Install deps
+ if: steps.yarn-node_modules.outputs.cache-hit != 'true'
+ uses: bahmutov/npm-install@v1
+ with:
+ install-command: corepack yarn --silent
+ env:
+ YARN_ENABLE_IMMUTABLE_INSTALLS: false
+
+ - name: run setup
+ run: |
+ npm run setup
+
+ - name: "NPM Identity"
+ env:
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+ run: |
+ echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc
+
+ - name: publish auto
+ if: github.event.inputs.release_type == 'auto'
+ run: |
+ npm run publish -- --force-publish --no-verify-access --no-private --no-commit-hooks --yes
+ env:
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: publish
+ if: github.event.inputs.release_type != 'auto'
+ run: |
+ npm run publish -- --force-publish --no-verify-access --no-private --no-commit-hooks --yes --bump ${{ github.event.inputs.release_type }}
+ env:
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index dd3b22f..204dcfb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,25 +1,62 @@
-.idea
-.vscode
-node_modules
+# NativeScript
+hooks/
+node_modules/
platforms
-hooks
-package-lock.json
+
+# NativeScript Template
+*.js.map
+!ngcc.config.js
+!webpack.config.js
+
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# General
.DS_Store
-npm-debug.log.*
-demo*/app/**/*.js
-demo*/typings
+.AppleDouble
+.LSOverride
+.idea
+.cloud
+.gradle
+.project
+.yarn
+.cxx
+tmp/
+
+!.eslintrc.js
+!.prettierrc.js
+
+!e2e/*.js
+!detox.config.js
+devices.js
+
*.framework
+*.xcframework
**/*.js.map
src/**/*.js
-plugin/**/*.js
-plugin/**/*.d.ts
+packages/**/*.js
+packages/**/*.d.ts
bin
build
Pods
-!plugin/platforms
-/plugin/platforms/android/*.aar
+!packages/*/platforms
+/packages/**/*.aar
+/packages/**/*.framework
+/packages/**/*.xcframework
+/demo-snippets/**/*.aar
*.xcuserdatad
-/plugin/README.md
-plugin/**/*js.map
-plugin/**/*js
-pnpm-lock.yaml
+/packages/README.md
+packages/**/*js.map
+packages/**/*js
+packages/typings
+packages/**/angular
+packages/**/*.ngsummary.json
+packages/**/*.metadata.json
+
+/blueprint.md
+
+*.tsbuildinfo
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..9c65367
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "demo-vue"]
+ path = demo-vue
+ url = https://github.com/nativescript-community/plugin-seed-demo-vue.git
+[submodule "tools"]
+ path = tools
+ url = https://github.com/nativescript-community/plugin-seed-tools.git
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..bf96d31
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1,11 @@
+shamefully-hoist=true
+public-hoist-pattern[]=*eslint*
+public-hoist-pattern[]=source-map-support
+public-hoist-pattern[]=ts-patch
+public-hoist-pattern[]=typescript
+public-hoist-pattern[]=cpy-cli
+strict-peer-dependencies=false
+shell-emulator=true
+auto-install-peers=false
+loglevel=error
+engine-strict=true
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..96d64cd
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,4 @@
+package-lock.json
+node_modules/
+plugin/
+docs/
diff --git a/.prettierrc b/.prettierrc
deleted file mode 100644
index e27ecb6..0000000
--- a/.prettierrc
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "printWidth": 200,
- "semi": true,
- "tabWidth": 4,
- "singleQuote": true
-}
\ No newline at end of file
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 0000000..2010c32
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,13 @@
+module.exports = {
+ plugins: ['prettier-plugin-svelte'],
+ overrides: [{ files: '*.svelte', options: { parser: 'svelte' } }],
+ printWidth: 200,
+ semi: true,
+ tabWidth: 4,
+ trailingComma: 'none',
+ singleQuote: true,
+ svelteSortOrder: 'options-styles-scripts-markup',
+ svelteStrictMode: false,
+ svelteBracketNewLine: false,
+ svelteIndentScriptAndStyle: true
+};
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 04347a5..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-matrix:
- include:
- - stage: "Lint"
- language: node_js
- os: linux
- node_js: "10"
- script: cd src && npm run ci.tslint
- - stage: "WebPack, Build"
- os: osx
- env:
- - WebPack="iOS"
- osx_image: xcode10.2
- language: node_js
- node_js: "10"
- jdk: oraclejdk8
- before_script: pod repo update
- script: cd demo && npm run build.plugin && npm i && tns build ios --bundle --env.uglify
- - language: android
- os: linux
- env:
- - WebPack="Android"
- dist: trusty
- jdk: oraclejdk8
- before_install: nvm install 10
- script: cd demo && npm run build.plugin && npm i && tns build android --bundle --env.uglify --env.snapshot
- - language: android
- env:
- - BuildAndroid="28"
- os: linux
- jdk: oraclejdk8
- dist: trusty
- before_install: nvm install 10
- script:
- - cd src && npm i && npm run tsc && cd ../demo && tns build android
- - os: osx
- osx_image: xcode10.2
- language: node_js
- node_js: "10"
- jdk: oraclejdk8
- before_script: pod repo update
- script:
- - cd src && npm i && npm run tsc && cd ../demo && tns build ios
-
-android:
- components:
- - tools
- - platform-tools
- - build-tools-28.0.3
- - android-28
- - extra-android-m2repository
- - sys-img-armeabi-v7a-android-21
-
-before_install:
- - sudo pip install --upgrade pip
- - sudo pip install six
-
-install:
- - echo no | npm install -g nativescript
- - tns usage-reporting disable
- - tns error-reporting disable
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..28eb5c5
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,51 @@
+{
+ "typescript.tsdk": "node_modules/typescript/lib",
+ "svelte.plugin.svelte.compilerWarnings": {
+ "missing-declaration": "ignore",
+ "a11y-aria-attributes": "ignore",
+ "a11y-incorrect-aria-attribute-type": "ignore",
+ "a11y-unknown-aria-attribute": "ignore",
+ "a11y-hidden": "ignore",
+ "a11y-misplaced-role": "ignore",
+ "a11y-unknown-role": "ignore",
+ "a11y-no-abstract-role": "ignore",
+ "a11y-no-redundant-roles": "ignore",
+ "a11y-role-has-required-aria-props": "ignore",
+ "a11y-accesskey": "ignore",
+ "a11y-autofocus": "ignore",
+ "a11y-misplaced-scope": "ignore",
+ "a11y-positive-tabindex": "ignore",
+ "a11y-invalid-attribute": "ignore",
+ "a11y-missing-attribute": "ignore",
+ "a11y-img-redundant-alt": "ignore",
+ "a11y-label-has-associated-control": "ignore",
+ "a11y-media-has-caption": "ignore",
+ "a11y-distracting-elements": "ignore",
+ "a11y-structure": "ignore",
+ "a11y-mouse-events-have-key-events": "ignore",
+ "a11y-missing-content": "ignore",
+ "illegal-attribute-character": "ignore"
+ },
+ "scss.lint.validProperties": [
+ "max-font-size",
+ "min-font-size",
+ "ios-a11y-adjusts-font-size",
+ "status-bar-style",
+ "navigation-bar-color",
+ "status-bar-color",
+ "ripple-color",
+ "stroke-color",
+ "fill-color",
+ "on-check-color",
+ "on-tint-color",
+ "shape",
+ "elevation",
+ "horizontal-align",
+ "horizontal-alignment",
+ "vertical-text-alignment",
+ "floating",
+ "vertical-alignment",
+ "placeholder-color",
+ "variant"
+ ]
+}
\ No newline at end of file
diff --git a/.yarnrc.yml b/.yarnrc.yml
new file mode 100644
index 0000000..80c89ad
--- /dev/null
+++ b/.yarnrc.yml
@@ -0,0 +1,5 @@
+compressionLevel: mixed
+
+nmHoistingLimits: workspaces
+
+nodeLinker: node-modules
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6c7021e..7cd35b8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,112 +3,480 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
-## [3.3.2](https://github.com/farfromrefug/nativescript-https/compare/v3.3.1...v3.3.2) (2021-10-21)
+## [4.1.32](https://github.com/nativescript-community/https/compare/v4.1.31...v4.1.32) (2026-03-31)
+
+### Bug Fixes
+* error when Blob does not exist ([f20e60b](https://github.com/nativescript-community/https/commit/f20e60b3f7d8e50033e4db837ea38a7a96c62f82))
+
+## [4.1.31](https://github.com/nativescript-community/https/compare/v4.1.30...v4.1.31) (2026-03-30)
### Bug Fixes
-* **android:** native-api-usage fix ([6f8748d](https://github.com/farfromrefug/nativescript-https/commit/6f8748da0323eb2520dbb5024301deb136bd5baa))
+* new getManager() method ([a232425](https://github.com/nativescript-community/https/commit/a232425fc8002301dc43d6a3f1786808953b0510))
+## [4.1.30](https://github.com/nativescript-community/https/compare/v4.1.29...v4.1.30) (2026-03-28)
+### Bug Fixes
+* ios fix for body and POST ([04c719a](https://github.com/nativescript-community/https/commit/04c719a1b0280b15f4fff639c0a21eded6b4a543))
+## [4.1.29](https://github.com/nativescript-community/https/compare/v4.1.28...v4.1.29) (2026-03-27)
-## [3.3.1](https://github.com/farfromrefug/nativescript-https/compare/v3.3.0...v3.3.1) (2021-10-18)
+### Bug Fixes
+
+* **https:** android application/x-www-form-urlencoded fix ([a133e53](https://github.com/nativescript-community/https/commit/a133e53409a24e64ded19c3c19d6ba948e8c46bc))
+## [4.1.28](https://github.com/nativescript-community/https/compare/v4.1.27...v4.1.28) (2026-03-26)
### Bug Fixes
-* **android:** native-api-usage fix ([e18a203](https://github.com/farfromrefug/nativescript-https/commit/e18a2039464d488f3e370dd7feaf6ed61e4938e6))
+* form data supports File type ([486f83f](https://github.com/nativescript-community/https/commit/486f83f398cc6bc6377ca6ef5b171f63653abfa0))
+## [4.1.27](https://github.com/nativescript-community/https/compare/v4.1.26...v4.1.27) (2026-01-14)
+### Bug Fixes
+* support ArrayBuffer/Blob for form data ([54140de](https://github.com/nativescript-community/https/commit/54140de323c0e9854c86444effaa02c3b8404529))
+## [4.1.26](https://github.com/nativescript-community/https/compare/v4.1.25...v4.1.26) (2025-12-18)
-# [3.3.0](https://github.com/farfromrefug/nativescript-https/compare/v3.2.2...v3.3.0) (2021-10-17)
+### Bug Fixes
+
+* prevent error with undefined/null headers entries ([e19d7b5](https://github.com/nativescript-community/https/commit/e19d7b557166a44b6d5b7d74077bb88651a70fc6))
+
+## [4.1.25](https://github.com/nativescript-community/https/compare/v4.1.24...v4.1.25) (2025-12-11)
+
+**Note:** Version bump only for package https
+
+## [4.1.24](https://github.com/nativescript-community/https/compare/v4.1.23...v4.1.24) (2025-12-11)
+
+**Note:** Version bump only for package https
+## [4.1.23](https://github.com/nativescript-community/https/compare/v4.1.22...v4.1.23) (2025-12-11)
### Bug Fixes
-* **android:** Conscrypt not included by default anymore. You need to add it in your app ([c16f34d](https://github.com/farfromrefug/nativescript-https/commit/c16f34d1b2f3fa226760ab00b17e56f6996dff96))
+* new option `runProgressOnMainThread` ([e53584a](https://github.com/nativescript-community/https/commit/e53584aa2f72fa917637da07987f6a763a69b59e))
+
+## [4.1.22](https://github.com/nativescript-community/https/compare/v4.1.21...v4.1.22) (2025-11-25)
+
+### Bug Fixes
+
+* **android:** improved cache control interceptor ([b92d084](https://github.com/nativescript-community/https/commit/b92d0847ea79370f5b76d0ff777c58954a29598a))
+
+## [4.1.21](https://github.com/nativescript-community/https/compare/v4.1.20...v4.1.21) (2025-10-29)
+
+### Bug Fixes
+
+* **android:** another native-api-usage fix ([f3e95a2](https://github.com/nativescript-community/https/commit/f3e95a2f3f4064a378082cf4d148bc797f2b600d))
+## [4.1.20](https://github.com/nativescript-community/https/compare/v4.1.19...v4.1.20) (2025-10-29)
### Features
-* **android:** native-api-usage ([9415f38](https://github.com/farfromrefug/nativescript-https/commit/9415f387b929b01c7fe385ff5d42e1bbd15ae2e4))
+* Expose native http error instance on failure ([17443fb](https://github.com/nativescript-community/https/commit/17443fb05044b41940ab2dcf04cb99f0e88d1f64))
+### Bug Fixes
+* **android:** native-api-usage fix ([43d8595](https://github.com/nativescript-community/https/commit/43d8595cf132d5705ec185a065fc9e7098d247b0))
+## [4.1.19](https://github.com/nativescript-community/https/compare/v4.1.18...v4.1.19) (2024-10-05)
+### Bug Fixes
-## [3.2.2](https://github.com/farfromrefug/nativescript-https/compare/v3.2.1...v3.2.2) (2021-07-21)
+* **ios:** should fix privacy submission issue ([299bd38](https://github.com/nativescript-community/https/commit/299bd3814b648e210c38a4910e537283718ca39b))
+## [4.1.18](https://github.com/nativescript-community/https/compare/v4.1.17...v4.1.18) (2024-09-26)
### Bug Fixes
-* **android:** prevent error when no cache-control ([e3d781e](https://github.com/farfromrefug/nativescript-https/commit/e3d781ed3a2d7364d3179d6a5acc39b5b9b65e29))
+* **ios:** prevent error ([67d096c](https://github.com/nativescript-community/https/commit/67d096cc30585b997423e52c32e52fdd93e37190))
+## [4.1.17](https://github.com/nativescript-community/https/compare/v4.1.16...v4.1.17) (2024-09-25)
+### Bug Fixes
+* **ios:** encoding fix for toString ([0a1221a](https://github.com/nativescript-community/https/commit/0a1221a3b5a3ecb6b736855eb242d7a5311918e2))
+* **ios:** Unexpected end of JSON input ([949fcfb](https://github.com/nativescript-community/https/commit/949fcfb9d154f0687ae76714ed12c091ed4dcf23))
+## [4.1.16](https://github.com/nativescript-community/https/compare/v4.1.15...v4.1.16) (2024-07-17)
-## [3.2.1](https://github.com/farfromrefug/nativescript-https/compare/v3.2.0...v3.2.1) (2021-07-01)
+### Bug Fixes
+* new `responseOnMainThread` option which allows running requests from worker ([71885b3](https://github.com/nativescript-community/https/commit/71885b30f26e5e70f6cdfdb61597cd7ff87d499c))
+
+## [4.1.15](https://github.com/nativescript-community/https/compare/v4.1.14...v4.1.15) (2024-07-16)
+
+### Features
+
+* Added support for removing cached responses using url ([9866da9](https://github.com/nativescript-community/https/commit/9866da95aaa4afdbf758967ca943e71b3c22ffcd))
### Bug Fixes
-* **android:** support for application/x-www-form-urlencoded ([fb8db51](https://github.com/farfromrefug/nativescript-https/commit/fb8db514916dd1c29baa40016fc5302c64a79a41))
+* Compiler warnings ([87a9631](https://github.com/nativescript-community/https/commit/87a9631143f5394f298047ef02308579bb8075bb))
+## [4.1.14](https://github.com/nativescript-community/https/compare/v4.1.13...v4.1.14) (2024-07-10)
+### Bug Fixes
+* android timeout ([d648278](https://github.com/nativescript-community/https/commit/d6482785485f60655227491b81f8c070889cb4e5))
+## [4.1.13](https://github.com/nativescript-community/https/compare/v4.1.12...v4.1.13) (2024-05-24)
-# [3.2.0](https://github.com/farfromrefug/nativescript-https/compare/v3.1.3...v3.2.0) (2021-03-14)
+### Bug Fixes
+
+* **android:** getImage fix ([dae5f65](https://github.com/nativescript-community/https/commit/dae5f6541a8ffe4ba561021b0bd4267aaeb8a92c))
+
+## [4.1.12](https://github.com/nativescript-community/https/compare/v4.1.11...v4.1.12) (2024-04-10)
+
+### Bug Fixes
+
+* **android:** prevent null exception ([73817e3](https://github.com/nativescript-community/https/commit/73817e3f706dc77b8ed78fc406bfe7eea1330839))
+
+## [4.1.11](https://github.com/nativescript-community/https/compare/v4.1.10...v4.1.11) (2024-04-09)
+
+### Bug Fixes
+
+* **android:** revert wraping native error so that app ([b23b7ca](https://github.com/nativescript-community/https/commit/b23b7ca73525a5c2e0176771d5a84a7be2d7a17b))
+
+## [4.1.10](https://github.com/nativescript-community/https/compare/v4.1.9...v4.1.10) (2024-03-29)
+
+### Bug Fixes
+
+* **android:** `forceCache` fix ([b3319ea](https://github.com/nativescript-community/https/commit/b3319ead68353f19e07a0eade5367ba7428e72fd))
+
+## [4.1.9](https://github.com/nativescript-community/https/compare/v4.1.8...v4.1.9) (2024-02-28)
+
+### Bug Fixes
+
+* **android:** wrap native errors in js Error ([c6f11c5](https://github.com/nativescript-community/https/commit/c6f11c5132116560d98901246f69d6ec52911917))
+
+## [4.1.8](https://github.com/nativescript-community/https/compare/v4.1.7...v4.1.8) (2023-11-21)
+
+### Bug Fixes
+
+* **ios:** ensure progress is run on main thread(for now) ([60a4453](https://github.com/nativescript-community/https/commit/60a44530f2371996a952c8566f2d9fded26d5b1e))
+
+## [4.1.7](https://github.com/nativescript-community/https/compare/v4.1.6...v4.1.7) (2023-11-21)
+
+## [4.1.5](https://github.com/nativescript-community/https/compare/v4.1.4...v4.1.5) (2023-11-02)
+
+### Bug Fixes
+
+* **ios:** rewrote to support all HTTP methods. ([4a25a73](https://github.com/nativescript-community/https/commit/4a25a73dc672e051370591e11e2dfe98127a60a5))
+## [4.1.6](https://github.com/nativescript-community/https/compare/v4.1.4...v4.1.6) (2023-11-13)
+
+### Bug Fixes
+
+* **android:** prevent error with GET and onProgress ([ae50812](https://github.com/nativescript-community/https/commit/ae508120411543c5a6822196dd890b29890a0804))
+* refactor to allow all HTTP methods. better support for uploading files ([b7ad6b9](https://github.com/nativescript-community/https/commit/b7ad6b99c7d8952249215e7170dcd4ca51070ddd))
+
+## [4.1.4](https://github.com/nativescript-community/https/compare/v4.1.3...v4.1.4) (2023-10-25)
+
+### Bug Fixes
+
+* **angular:** xhr factory import ([71a3609](https://github.com/nativescript-community/https/commit/71a3609abd8a0180f1519b051b02e633605bdfe1))
+
+## [4.1.3](https://github.com/nativescript-community/https/compare/v4.1.2...v4.1.3) (2023-10-19)
### Features
-* **android:** forceCache option ([cc225be](https://github.com/farfromrefug/nativescript-https/commit/cc225bea37e0035288533106e48a469e11d15d01))
+* **angular:** handle params ([eff8222](https://github.com/nativescript-community/https/commit/eff82226bf4727b73d8484014245956248931d70))
+## [4.1.2](https://github.com/nativescript-community/https/compare/v4.1.1...v4.1.2) (2023-08-30)
+### Bug Fixes
+* **android:** toBitmapAsync is not a function error fix ([63b19f0](https://github.com/nativescript-community/https/commit/63b19f03334d8ae742dddc47d48db530d88db63f))
+* **ios:** base URL for AFHTTPSessionManager ([0ee4640](https://github.com/nativescript-community/https/commit/0ee46405eed8fe2902b01ddb1f871f604424bf51))
+* **ios:** non legacy report format fix ([1cec77e](https://github.com/nativescript-community/https/commit/1cec77ef3144c4840fb205142aa4d7e761262196))
+## [4.1.1](https://github.com/nativescript-community/https/compare/v4.1.0...v4.1.1) (2023-07-03)
-## [3.1.3](https://github.com/farfromrefug/nativescript-https/compare/v3.1.2...v3.1.3) (2021-03-12)
+### Bug Fixes
+
+* angular build ([0290951](https://github.com/nativescript-community/https/commit/0290951a20d41a9158e406f6120ea9f2a1459219))
+* angular code formatting & error handling ([e1893e4](https://github.com/nativescript-community/https/commit/e1893e4481793abecf32bb44ef6185c498935d2d))
+* call async methods to prevent android.os.NetworkOnMainThreadException errors ([ec82cef](https://github.com/nativescript-community/https/commit/ec82cef78897de459f879b42f3a83eb7504d5fec))
+
+# [4.1.0](https://github.com/nativescript-community/https/compare/v4.0.17...v4.1.0) (2023-04-30)
+
+### Features
+
+* angular module ([dc3761a](https://github.com/nativescript-community/https/commit/dc3761ac33d99ddaa35d47e56c3275774af647f1))
+* angular support ([ff92deb](https://github.com/nativescript-community/https/commit/ff92deb51bc95605c02eafe9ae4f066434fe8dcd))
+## [4.0.17](https://github.com/nativescript-community/https/compare/v4.0.16...v4.0.17) (2023-03-20)
### Bug Fixes
-* **android:** correctly use timeout option ([9a1e5be](https://github.com/farfromrefug/nativescript-https/commit/9a1e5be39f70453653d8cbc38c66ddf6843754ce))
+* **android:** support native data for form data parameters ([47e9002](https://github.com/nativescript-community/https/commit/47e9002ddd4c1ec8acf106035e36c6649829ae85))
+## [4.0.16](https://github.com/nativescript-community/https/compare/v4.0.15...v4.0.16) (2023-03-14)
+### Features
+* `cancelAllRequests` ([3a014bc](https://github.com/nativescript-community/https/commit/3a014bc9fe797d9b1405b9ed75348fba776d6eb2))
+## [4.0.15](https://github.com/nativescript-community/https/compare/v4.0.14...v4.0.15) (2023-03-06)
-## [3.1.2](https://github.com/farfromrefug/nativescript-https/compare/v3.1.1...v3.1.2) (2020-12-09)
+### Bug Fixes
+* **android:** update to latest okhttp lib ([c4b7870](https://github.com/nativescript-community/https/commit/c4b78703637e21bbfa84647d7f8a6f07348c9f44))
+
+### Features
+
+* **android:** support passing custom RequestBody as `content` parameter ([4e5b513](https://github.com/nativescript-community/https/commit/4e5b5136f19487a87911638ef4b9fc7a174dd619))
+
+## [4.0.14](https://github.com/nativescript-community/https/compare/v4.0.13...v4.0.14) (2023-02-15)
### Bug Fixes
-* ios crash with cache on < 13 ([e021b8d](https://github.com/farfromrefug/nativescript-https/commit/e021b8d9c847f5ba545cc6fc52e6271780dd4e7f))
+* **android:** cookiesEnabled: false fixed ([94f6bb1](https://github.com/nativescript-community/https/commit/94f6bb18c546ef1e427730d45cc71a4726f9ab39))
+## [4.0.13](https://github.com/nativescript-community/https/compare/v4.0.12...v4.0.13) (2023-01-24)
+### Bug Fixes
+* **android:** native-api-usage fix ([0f5ca06](https://github.com/nativescript-community/https/commit/0f5ca062c06c0f2c31677be8c528c1b072070e50))
+## [4.0.12](https://github.com/nativescript-community/https/compare/v4.0.11...v4.0.12) (2023-01-23)
-## [3.1.1](https://github.com/farfromrefug/nativescript-https/compare/v3.1.0...v3.1.1) (2020-11-26)
+### Bug Fixes
+
+* **android:** improved native-api-usage ([5e32bb0](https://github.com/nativescript-community/https/commit/5e32bb08e3f95c75e0ec05d0594294911eda72af))
+
+## [4.0.11](https://github.com/nativescript-community/https/compare/v4.0.10...v4.0.11) (2022-12-05)
+
+### Features
+
+* clearCookies method ([5410f6e](https://github.com/nativescript-community/https/commit/5410f6e86202ca74b31fea0f94fda95467c13e38))
+## [4.0.10](https://github.com/nativescript-community/https/compare/v4.0.9...v4.0.10) (2022-11-02)
### Bug Fixes
-* correctly handle null responses from requests ([6b70be6](https://github.com/farfromrefug/nativescript-https/commit/6b70be64eb44a7e3da1705f025128bd9fabe6d2a))
+* **ios:** correctly send JSON body with null values ([8ba7085](https://github.com/nativescript-community/https/commit/8ba70858927adef23b2a0eeea32827bff975457b))
+## [4.0.9](https://github.com/nativescript-community/https/compare/v4.0.8...v4.0.9) (2022-11-02)
+### Bug Fixes
+* **ios:** prevent crash on request failure ([c9485e5](https://github.com/nativescript-community/https/commit/c9485e57833946c858682899b09d2c504d445fbc))
+## [4.0.8](https://github.com/nativescript-community/https/compare/v4.0.7...v4.0.8) (2022-09-17)
-# 3.1.0 (2020-10-29)
+### Features
+
+* export getClient for use with ui-image plugin ([50a5f4a](https://github.com/nativescript-community/https/commit/50a5f4a6657c93a441df7f55f6a0b392f3c2b251))
+
+## [4.0.7](https://github.com/nativescript-community/https/compare/v4.0.6...v4.0.7) (2022-09-17)
+
+### Features
+
+* added `cookiesEnabled` property (`true` by default) ([19aeb27](https://github.com/nativescript-community/https/commit/19aeb27f469e989c8d71b48aa32139c8faa66cd2))
+
+## [4.0.6](https://github.com/nativescript-community/https/compare/v4.0.5...v4.0.6) (2022-05-18)
+
+### Bug Fixes
+
+* **android:** cancelling of long process requests fix ([e46b698](https://github.com/nativescript-community/https/commit/e46b698d106ccf3239ecbee5f7ea3a39192a50f5))
+
+## [4.0.5](https://github.com/nativescript-community/https/compare/v4.0.4...v4.0.5) (2022-04-28)
+
+### Bug Fixes
+
+* **android:** trying to fix kotlin crashes ([9c75476](https://github.com/nativescript-community/https/commit/9c7547690b72163c325e0137ad386cf51ab33db6))
+## [4.0.4](https://github.com/nativescript-community/https/compare/v4.0.3...v4.0.4) (2022-04-26)
+
+### Bug Fixes
+
+* **android:** should work now ([7368616](https://github.com/nativescript-community/https/commit/7368616735cdb4d3110c04a5fc19800327b5e3ed))
+
+## [4.0.3](https://github.com/nativescript-community/https/compare/v4.0.2...v4.0.3) (2022-04-26)
+
+### Bug Fixes
+
+* **android:** another fix... ([8cd3c92](https://github.com/nativescript-community/https/commit/8cd3c92980faeb6b87dfe6799b56b3b0a9375e60))
+
+## [4.0.2](https://github.com/nativescript-community/https/compare/v4.0.1...v4.0.2) (2022-04-26)
+
+### Bug Fixes
+
+* **android:** broken headers in response ([81d8479](https://github.com/nativescript-community/https/commit/81d8479a5dd44fb1e51212b8842c3409b7c23ed3))
+
+## [4.0.1](https://github.com/nativescript-community/https/compare/v4.0.0...v4.0.1) (2022-04-25)
+
+### Bug Fixes
+
+* **android:** crash on response headers ([b09da7f](https://github.com/nativescript-community/https/commit/b09da7f3e357e5b3047b73227f7c29d2efb93ced))
+
+# [4.0.0](https://github.com/nativescript-community/https/compare/v3.4.4...v4.0.0) (2022-04-25)
+
+### Features
+
+* **android:** upgrade okhttp to 4.x. WARNING: minSDKVersion bumped to 21!
+
+## [3.4.4](https://github.com/nativescript-community/https/compare/v3.4.3...v3.4.4) (2022-04-25)
+
+### Bug Fixes
+
+* **android:** dont try/catch sync methods to prevent missed errors ([cb830a8](https://github.com/nativescript-community/https/commit/cb830a8cad414133bcdff4a14c986cb8899984e6))
+* **android:** upgrade okhttp to max 3.x ([eb0b61e](https://github.com/nativescript-community/https/commit/eb0b61ea8ba53055538d5460abf0474a22ba3282))
+
+## [3.4.3](https://github.com/nativescript-community/https/compare/v3.4.2...v3.4.3) (2022-04-25)
+
+### Bug Fixes
+
+* **android:** native-api-usage fix ([bc3c7d2](https://github.com/nativescript-community/https/commit/bc3c7d24160038f48e487918ee8abcf5d24f0322))
+
+### Features
+
+* contentLength ([a2e1017](https://github.com/nativescript-community/https/commit/a2e10170145a8e94e10f407e5fe772cb0d40e12c))
+
+## [3.4.2](https://github.com/nativescript-community/https/compare/v3.4.1...v3.4.2) (2022-02-26)
+
+### Bug Fixes
+
+* completely broken release … ([b35209e](https://github.com/nativescript-community/https/commit/b35209e98ebd87a196512a84b68b67c79ffb1341))
+
+## [3.4.1](https://github.com/nativescript-community/https/compare/v3.4.0...v3.4.1) (2022-02-26)
+
+### Bug Fixes
+
+* **android:** fixed broken build ([532ae49](https://github.com/nativescript-community/https/commit/532ae49a0dbe6c9dc4742400051d5ea86646ebbc))
+
+# [3.4.0](https://github.com/nativescript-community/https/compare/v3.3.13...v3.4.0) (2022-02-25)
+
+### Features
+
+* refactoring to allow N alias to replace core impl ([22ac92f](https://github.com/nativescript-community/https/commit/22ac92f572c9b2739c40f5a39f47ac67d28a78ee))
+
+## [3.3.13](https://github.com/nativescript-community/https/compare/v3.3.12...v3.3.13) (2022-02-08)
+
+### Bug Fixes
+
+* **ios:** fix form data passed as a string ([d234842](https://github.com/nativescript-community/https/commit/d234842c5a29b8a360aae6c91dce80821630eea1))
+
+## [3.3.12](https://github.com/nativescript-community/https/compare/v3.3.11...v3.3.12) (2022-01-20)
+
+### Bug Fixes
+
+* **android:** progress support for uploading ([67817ac](https://github.com/nativescript-community/https/commit/67817ac284f8da424829b0c400b5c2c788ccf9dc))
+
+## [3.3.11](https://github.com/nativescript-community/https/compare/v3.3.10...v3.3.11) (2022-01-20)
+
+### Bug Fixes
+
+* **android:** native-api-usage fix ([06dc376](https://github.com/nativescript-community/https/commit/06dc376b01683675ef2a90135396ec5a9f1cf60a))
+
+## [3.3.10](https://github.com/nativescript-community/https/compare/v3.3.9...v3.3.10) (2022-01-19)
+
+### Bug Fixes
+
+* typings fix ([3490469](https://github.com/nativescript-community/https/commit/3490469cdc019265ec321ff9db37b94100f94b49))
+
+## [3.3.9](https://github.com/nativescript-community/https/compare/v3.3.8...v3.3.9) (2022-01-18)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.3.8](https://github.com/farfromrefug/nativescript-https/compare/v3.3.7...v3.3.8) (2022-01-18)
+
+### Bug Fixes
+
+* **android:** `cancelRequest` fix ([c7b8c93](https://github.com/farfromrefug/nativescript-https/commit/c7b8c935a6b02dc4f9e5c20c6911b2e59db8fa64))
+
+## [3.3.7](https://github.com/farfromrefug/nativescript-https/compare/v3.3.6...v3.3.7) (2022-01-15)
+
+### Bug Fixes
+
+* **android:** `cancelRequest` not exported ([9727802](https://github.com/farfromrefug/nativescript-https/commit/972780279a291d3f95636601450198a78d935696))
+
+## [3.3.6](https://github.com/farfromrefug/nativescript-https/compare/v3.3.5...v3.3.6) (2022-01-15)
+
+### Features
+
+* added method `cancelRequest`. You need to set the `tag` in request options first ([bace983](https://github.com/farfromrefug/nativescript-https/commit/bace9832d9ab07b158068eca3104a24f4c494851))
+
+## [3.3.5](https://github.com/farfromrefug/nativescript-https/compare/v3.3.4...v3.3.5) (2022-01-14)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.3.4](https://github.com/farfromrefug/nativescript-https/compare/v3.3.3...v3.3.4) (2022-01-14)
+
+### Bug Fixes
+
+* **android:** missing native-api-usage ([0d6d67b](https://github.com/farfromrefug/nativescript-https/commit/0d6d67b223e52d5e3d80b4513f2ee6d591495e4f))
+* missing export of `addNetworkInterceptor`, `addInterceptor` ([2b503c4](https://github.com/farfromrefug/nativescript-https/commit/2b503c42d43cde3f82d994346948e20bbf91fc57))
+
+## [3.3.3](https://github.com/farfromrefug/nativescript-https/compare/v3.3.2...v3.3.3) (2021-12-23)
+
+### Bug Fixes
+
+* android allow interceptors ([49073c5](https://github.com/farfromrefug/nativescript-https/commit/49073c5c4e1ab1370da4260ebc833705eaabb2b3))
+
+## [3.3.2](https://github.com/farfromrefug/nativescript-https/compare/v3.3.1...v3.3.2) (2021-10-21)
+
+### Bug Fixes
+
+* **android:** native-api-usage fix ([6f8748d](https://github.com/farfromrefug/nativescript-https/commit/6f8748da0323eb2520dbb5024301deb136bd5baa))
+
+## [3.3.1](https://github.com/farfromrefug/nativescript-https/compare/v3.3.0...v3.3.1) (2021-10-18)
+
+### Bug Fixes
+
+* **android:** native-api-usage fix ([e18a203](https://github.com/farfromrefug/nativescript-https/commit/e18a2039464d488f3e370dd7feaf6ed61e4938e6))
+
+# [3.3.0](https://github.com/farfromrefug/nativescript-https/compare/v3.2.2...v3.3.0) (2021-10-17)
+
+### Bug Fixes
+
+* **android:** Conscrypt not included by default anymore. You need to add it in your app ([c16f34d](https://github.com/farfromrefug/nativescript-https/commit/c16f34d1b2f3fa226760ab00b17e56f6996dff96))
+
+### Features
+
+* **android:** native-api-usage ([9415f38](https://github.com/farfromrefug/nativescript-https/commit/9415f387b929b01c7fe385ff5d42e1bbd15ae2e4))
+
+## [3.2.2](https://github.com/farfromrefug/nativescript-https/compare/v3.2.1...v3.2.2) (2021-07-21)
+
+### Bug Fixes
+
+* **android:** prevent error when no cache-control ([e3d781e](https://github.com/farfromrefug/nativescript-https/commit/e3d781ed3a2d7364d3179d6a5acc39b5b9b65e29))
+
+## [3.2.1](https://github.com/farfromrefug/nativescript-https/compare/v3.2.0...v3.2.1) (2021-07-01)
+
+### Bug Fixes
+
+* **android:** support for application/x-www-form-urlencoded ([fb8db51](https://github.com/farfromrefug/nativescript-https/commit/fb8db514916dd1c29baa40016fc5302c64a79a41))
+
+# [3.2.0](https://github.com/farfromrefug/nativescript-https/compare/v3.1.3...v3.2.0) (2021-03-14)
+
+### Features
+
+* **android:** forceCache option ([cc225be](https://github.com/farfromrefug/nativescript-https/commit/cc225bea37e0035288533106e48a469e11d15d01))
+
+## [3.1.3](https://github.com/farfromrefug/nativescript-https/compare/v3.1.2...v3.1.3) (2021-03-12)
+
+### Bug Fixes
+
+* **android:** correctly use timeout option ([9a1e5be](https://github.com/farfromrefug/nativescript-https/commit/9a1e5be39f70453653d8cbc38c66ddf6843754ce))
+
+## [3.1.2](https://github.com/farfromrefug/nativescript-https/compare/v3.1.1...v3.1.2) (2020-12-09)
+
+### Bug Fixes
+
+* ios crash with cache on < 13 ([e021b8d](https://github.com/farfromrefug/nativescript-https/commit/e021b8d9c847f5ba545cc6fc52e6271780dd4e7f))
+
+## [3.1.1](https://github.com/farfromrefug/nativescript-https/compare/v3.1.0...v3.1.1) (2020-11-26)
+
+### Bug Fixes
+
+* correctly handle null responses from requests ([6b70be6](https://github.com/farfromrefug/nativescript-https/commit/6b70be64eb44a7e3da1705f025128bd9fabe6d2a))
+
+# 3.1.0 (2020-10-29)
### Bug Fixes
@@ -132,7 +500,6 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
* useLegacy should be a request option ([74f1afa](https://github.com/farfromrefug/nativescript-https/commit/74f1afabfeb051c08b89050b17771356381bd03c))
* **ios:** multipart fix ([0d9d331](https://github.com/farfromrefug/nativescript-https/commit/0d9d331ff49cedd06ed0d07cd25a4b50181a23a5))
-
### Features
* basick cookie support ([91fe3c7](https://github.com/farfromrefug/nativescript-https/commit/91fe3c7d6b8fd7f4198845bd9f88324ccb384704))
@@ -141,22 +508,12 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
* move to @nativescript-community/https ([5c8d5c8](https://github.com/farfromrefug/nativescript-https/commit/5c8d5c8c4e5e7d50a0312cf978638b6068398025))
* multi formdata support ([c1dff6d](https://github.com/farfromrefug/nativescript-https/commit/c1dff6d27bcad54fb4f7aa03180a73696fc17ce2))
-
-
# 2.1.0 (2020-04-07)
-
-
# 2.0.0 (2020-03-30)
-
-
# 1.3.0 (2020-02-13)
-
-
## 1.2.2 (2019-10-16)
-
-
# 1.2.0 (2019-10-06)
diff --git a/README.md b/README.md
index 5df82d4..a10faaa 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,103 @@
-# @nativescript-community/https
-
-[![NPM version][npm-image]][npm-url]
-[![Downloads][downloads-image]][npm-url]
-[![TotalDownloads][total-downloads-image]][npm-url]
-[![Twitter Follow][twitter-image]][twitter-url]
-
-[build-status]: https://travis-ci.org/nativescript-community/https.svg?branch=master
-[build-url]: https://travis-ci.org/nativescript-community/https
-[npm-image]: http://img.shields.io/npm/v/@nativescript-community/https.svg
-[npm-url]: https://npmjs.org/package/@nativescript-community/https
-[downloads-image]: http://img.shields.io/npm/dm/@nativescript-community/https.svg
-[total-downloads-image]: http://img.shields.io/npm/dt/@nativescript-community/https.svg?label=total%20downloads
-[twitter-image]: https://img.shields.io/twitter/follow/eddyverbruggen.svg?style=social&label=Follow%20me
-[twitter-url]: https://twitter.com/eddyverbruggen
+
+
+
@nativescript-community/https
+
+
+
+
+
+
+ Nativescript plugin for https requests
+
+
+
+
+
+
+
+[](#table-of-contents)
+
+
+[](#table-of-contents)
+
+## Table of Contents
+
+ * [Installation](#installation)
+ * [A drop-in replacement for the [default http module](https://docs.nativescript.org/cookbook/http).](#a-drop-in-replacement-for-the-default-http-modulehttpsdocsnativescriptorgcookbookhttp)
+ * [Features](#features)
+ * [FAQ](#faq)
+ * [Installation](#installation-1)
+ * [Examples](#examples)
+ * [Hitting an API using `GET` method](#hitting-an-api-using-get-method)
+ * [Configuration](#configuration)
+ * [Installing your SSL certificate](#installing-your-ssl-certificate)
+ * [Enabling SSL pinning](#enabling-ssl-pinning)
+ * [Disabling SSL pinning](#disabling-ssl-pinning)
+ * [useLegacy](#uselegacy)
+ * [Cookie](#cookie)
+ * [Enabling Cache](#enabling-cache)
+ * [Multipart form data](#multipart-form-data)
+ * [Options](#options)
+ * [Webpack / bundling](#webpack--bundling)
+ * [`iOS` Troubleshooting](#ios-troubleshooting)
+ * [`Android` troubleshooting](#android-troubleshooting)
+* [Thanks](#thanks)
+ * [Examples:](#examples-1)
+ * [Demos and Development](#demos-and-development)
+ * [Repo Setup](#repo-setup)
+ * [Build](#build)
+ * [Demos](#demos)
+ * [Contributing](#contributing)
+ * [Update repo ](#update-repo-)
+ * [Update readme ](#update-readme-)
+ * [Update doc ](#update-doc-)
+ * [Publish](#publish)
+ * [modifying submodules](#modifying-submodules)
+ * [Questions](#questions)
+
+
+[](#installation)
+
+
+[](#installation)
+
+## Installation
+Run the following command from the root of your project:
-### The definitive way to hit HTTP based APIs in Nativescript.
+`ns plugin add @nativescript-community/https`
Easily integrate the most reliable native networking libraries with the latest and greatest HTTPS security features.
+> Android: version 4.x using okhttp 4.x changing minSDKVersion to 21! If lower needed stick to 3.x
+
> Plugin version 2.0.0 bumps `AFNetworking` on iOS to [4.0.0](https://github.com/AFNetworking/AFNetworking/releases/tag/4.0.0) which no longer relies on `UIWebView`. Make sure to run `pod repo update` to get the latest `AFNetworking` pod on your development machine.
-#### A drop-in replacement for the [default http module](https://docs.nativescript.org/cookbook/http#get-response-status-code).
+#### A drop-in replacement for the [default http module](https://docs.nativescript.org/cookbook/http).
+
+[](#features)
+
+
+[](#features)
+
## Features
- Modern TLS & SSL security features
@@ -34,6 +110,12 @@ Easily integrate the most reliable native networking libraries with the latest a
- Cache
- Basic Cookie support
+
+[](#faq)
+
+
+[](#faq)
+
## FAQ
> What the flip is SSL pinning and all this security mumbo jumbo?
@@ -44,33 +126,25 @@ Easily integrate the most reliable native networking libraries with the latest a
**No.** This plugin works out of the box without any security configurations needed. Either way you'll still benefit from all the features listed above.
-## Demo
-
-```shell
-git clone https://github.com/nativescript-community/https
-cd https
-npm run demo.ios
-npm run demo.android
-```
+
+[](#installation)
+
+
+[](#installation)
+
## Installation
-#### Add `tns-platform-declarations` for Android and iOS to your `references.d.ts`!
-
-```typescript
-///
-///
-```
-
-We also recommend adding `"skipLibCheck": true,` to your `tsconfig.json`.
-More information on that can be found [here](https://github.com/NativeScript/NativeScript/tree/master/tns-platform-declarations).
-
-Install the plugin:
-
```bash
tns plugin add @nativescript-community/https
```
+
+[](#examples)
+
+
+[](#examples)
+
## Examples
### Hitting an API using `GET` method
@@ -90,6 +164,12 @@ Https.request({
});
```
+
+[](#configuration)
+
+
+[](#configuration)
+
## Configuration
### Installing your SSL certificate
@@ -193,11 +273,23 @@ export interface HttpsRequestOptions extends HTTPOptions {
| `cachePolicy?: 'noCache' | 'onlyCache' | 'ignoreCache'` | Set the cache policy to use with that request. This only works with GET requests for now. |
| `onProgress?: (current: number, total: number) => void` | [IOS only] Set the progress callback. |
+
+[](#webpack--bundling)
+
+
+[](#webpack--bundling)
+
## Webpack / bundling
Since you're probably shipping a certificate with your app (like [our demo does](https://github.com/nativescript-community/https/tree/master/demo/app/assets)),
make sure it's bundled by Webpack as well. You can do this by [adding the certificate(s) with the `CopyWebpackPlugin`](https://github.com/nativescript-community/https/blob/a5c841c0af7ff6d9994fa23f7fba0df0514c58f1/demo/webpack.config.js#L240).
+
+[](#ios-troubleshooting)
+
+
+[](#ios-troubleshooting)
+
## `iOS` Troubleshooting
> ### Please educate yourself on iOS's [App Transport Security](https://github.com/codepath/ios_guides/wiki/App-Transport-Security) before starting beef!
@@ -215,15 +307,239 @@ You can bypass this behavior by adding the following to your projects `Info.plis
> This plugin **does not** add `NSAllowsArbitraryLoads` to your projects `Info.plist` for you.
+
+[](#android-troubleshooting)
+
+
+[](#android-troubleshooting)
+
## `Android` troubleshooting
-If you app crashes with a message that it's doing too much networkin on the main thread,
+If you app crashes with a message that it's doing too much networking on the main thread,
then pass the option `allowLargeResponse` with value `true` to the `request` function.
+
+[](#thanks)
+
+
+[](#thanks)
+
# Thanks
| Who | Why |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| [Robert Laverty](https://github.com/roblav96) | For creating and maintaining this plugin for a long time, before transfering it to me, with the help of Jeff Whelpley of [GetHuman](https://github.com/gethuman). |
+| [Robert Laverty](https://github.com/roblav96) | For creating and maintaining this plugin for a long time |
+| [Jeff Whelple](https://github.com/gethuman) | For contributing |
+| [Eddy Verbruggen](https://github.com/EddyVerbruggen) | For maintaining this before it got transferred |
| [AFNetworking](https://github.com/AFNetworking) | [AFNetworking](https://github.com/AFNetworking/AFNetworking) A delightful networking framework for iOS, OS X, watchOS, and tvOS. |
| [Square](http://square.github.io/) | [okhttp](https://github.com/square/okhttp) An HTTP+HTTP/2 client for Android and Java applications. |
+
+### Examples:
+
+- [Basic](demo-snippets/vue/Basic.vue)
+ - A basic example
+
+
+[](#demos-and-development)
+
+
+[](#demos-and-development)
+
+## Demos and Development
+
+
+### Repo Setup
+
+The repo uses submodules. If you did not clone with ` --recursive` then you need to call
+```
+git submodule update --init
+```
+
+The package manager used to install and link dependencies must be `pnpm` or `yarn`. `npm` wont work.
+
+To develop and test:
+if you use `yarn` then run `yarn`
+if you use `pnpm` then run `pnpm i`
+
+**Interactive Menu:**
+
+To start the interactive menu, run `npm start` (or `yarn start` or `pnpm start`). This will list all of the commonly used scripts.
+
+### Build
+
+```bash
+npm run build.all
+```
+WARNING: it seems `yarn build.all` wont always work (not finding binaries in `node_modules/.bin`) which is why the doc explicitly uses `npm run`
+
+### Demos
+
+```bash
+npm run demo.[ng|react|svelte|vue].[ios|android]
+
+npm run demo.svelte.ios # Example
+```
+
+Demo setup is a bit special in the sense that if you want to modify/add demos you dont work directly in `demo-[ng|react|svelte|vue]`
+Instead you work in `demo-snippets/[ng|react|svelte|vue]`
+You can start from the `install.ts` of each flavor to see how to register new demos
+
+
+[](#contributing)
+
+
+[](#contributing)
+
+## Contributing
+
+### Update repo
+
+You can update the repo files quite easily
+
+First update the submodules
+
+```bash
+npm run update
+```
+
+Then commit the changes
+Then update common files
+
+```bash
+npm run sync
+```
+Then you can run `yarn|pnpm`, commit changed files if any
+
+### Update readme
+```bash
+npm run readme
+```
+
+### Update doc
+```bash
+npm run doc
+```
+
+### Publish
+
+The publishing is completely handled by `lerna` (you can add `-- --bump major` to force a major release)
+Simply run
+```shell
+npm run publish
+```
+
+### modifying submodules
+
+The repo uses https:// for submodules which means you won't be able to push directly into the submodules.
+One easy solution is t modify `~/.gitconfig` and add
+```
+[url "ssh://git@github.com/"]
+ pushInsteadOf = https://github.com/
+```
+
+
+[](#questions)
+
+
+[](#questions)
+
+## Questions
+
+If you have any questions/issues/comments please feel free to create an issue or start a conversation in the [NativeScript Community Discord](https://nativescript.org/discord).
+
+[](#demos-and-development)
+
+## Demos and Development
+
+
+### Repo Setup
+
+The repo uses submodules. If you did not clone with ` --recursive` then you need to call
+```
+git submodule update --init
+```
+
+The package manager used to install and link dependencies must be `pnpm` or `yarn`. `npm` wont work.
+
+To develop and test:
+if you use `yarn` then run `yarn`
+if you use `pnpm` then run `pnpm i`
+
+**Interactive Menu:**
+
+To start the interactive menu, run `npm start` (or `yarn start` or `pnpm start`). This will list all of the commonly used scripts.
+
+### Build
+
+```bash
+npm run build.all
+```
+WARNING: it seems `yarn build.all` wont always work (not finding binaries in `node_modules/.bin`) which is why the doc explicitly uses `npm run`
+
+### Demos
+
+```bash
+npm run demo.[ng|react|svelte|vue].[ios|android]
+
+npm run demo.svelte.ios # Example
+```
+
+Demo setup is a bit special in the sense that if you want to modify/add demos you dont work directly in `demo-[ng|react|svelte|vue]`
+Instead you work in `demo-snippets/[ng|react|svelte|vue]`
+You can start from the `install.ts` of each flavor to see how to register new demos
+
+
+[](#contributing)
+
+## Contributing
+
+### Update repo
+
+You can update the repo files quite easily
+
+First update the submodules
+
+```bash
+npm run update
+```
+
+Then commit the changes
+Then update common files
+
+```bash
+npm run sync
+```
+Then you can run `yarn|pnpm`, commit changed files if any
+
+### Update readme
+```bash
+npm run readme
+```
+
+### Update doc
+```bash
+npm run doc
+```
+
+### Publish
+
+The publishing is completely handled by `lerna` (you can add `-- --bump major` to force a major release)
+Simply run
+```shell
+npm run publish
+```
+
+### modifying submodules
+
+The repo uses https:// for submodules which means you won't be able to push directly into the submodules.
+One easy solution is t modify `~/.gitconfig` and add
+```
+[url "ssh://git@github.com/"]
+ pushInsteadOf = https://github.com/
+```
+
+[](#questions)
+
+## Questions
+
+If you have any questions/issues/comments please feel free to create an issue or start a conversation in the [NativeScript Community Discord](https://nativescript.org/discord).
\ No newline at end of file
diff --git a/config.json b/config.json
new file mode 100644
index 0000000..6db1ce0
--- /dev/null
+++ b/config.json
@@ -0,0 +1,7 @@
+{
+ "readme": true,
+ "angular": true,
+ "demos": [
+ "vue"
+ ]
+}
\ No newline at end of file
diff --git a/demo/app/assets/httpbin.org.cer b/demo-snippets/assets/httpbin.org.cer
similarity index 100%
rename from demo/app/assets/httpbin.org.cer
rename to demo-snippets/assets/httpbin.org.cer
diff --git a/demo/app/assets/httpbin.org.expired.cer b/demo-snippets/assets/httpbin.org.expired.cer
similarity index 100%
rename from demo/app/assets/httpbin.org.expired.cer
rename to demo-snippets/assets/httpbin.org.expired.cer
diff --git a/demo-snippets/package.json b/demo-snippets/package.json
new file mode 100644
index 0000000..384c7ba
--- /dev/null
+++ b/demo-snippets/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "@nativescript-community/template-snippet",
+ "private": true,
+ "version": "0.0.1",
+ "dependencies": {
+ "@nativescript-community/https": "4.0.11"
+ },
+ "nativescript": {
+ "platforms": {
+ "android": "2.3.0",
+ "ios": "2.3.0"
+ }
+ }
+}
diff --git a/demo-snippets/vue/Basic.vue b/demo-snippets/vue/Basic.vue
new file mode 100644
index 0000000..7f50af3
--- /dev/null
+++ b/demo-snippets/vue/Basic.vue
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo-snippets/vue/install.ts b/demo-snippets/vue/install.ts
new file mode 100644
index 0000000..3d1b976
--- /dev/null
+++ b/demo-snippets/vue/install.ts
@@ -0,0 +1,18 @@
+import Vue from 'nativescript-vue';
+import Basic from './Basic.vue';
+import * as Https from '@nativescript-community/https';
+import * as fs from '@nativescript/core/file-system';
+
+const folder = fs.knownFolders.temp().getFolder('cache');
+const diskLocation = folder.path;
+const cacheSize = 10 * 1024 * 1024;
+Https.setCache({
+ // forceCache: true,
+ diskLocation,
+ diskSize: cacheSize,
+ memorySize: cacheSize
+});
+
+export function installPlugin() {}
+
+export const demos = [{ name: 'Basic', path: 'basic', component: Basic }];
diff --git a/demo-vue b/demo-vue
new file mode 160000
index 0000000..ef6f78f
--- /dev/null
+++ b/demo-vue
@@ -0,0 +1 @@
+Subproject commit ef6f78fe04b61ea05dca21c61a6c2515b1b46b7e
diff --git a/demo/app/App_Resources/Android/app.gradle b/demo/app/App_Resources/Android/app.gradle
deleted file mode 100644
index 8c5b9f8..0000000
--- a/demo/app/App_Resources/Android/app.gradle
+++ /dev/null
@@ -1,9 +0,0 @@
-android {
- defaultConfig {
- generatedDensities = []
- applicationId = "org.nativescript.plugindemo.https"
- }
- aaptOptions {
- additionalParameters "--no-version-vectors"
- }
-}
diff --git a/demo/app/App_Resources/Android/src/main/AndroidManifest.xml b/demo/app/App_Resources/Android/src/main/AndroidManifest.xml
deleted file mode 100644
index 9db8321..0000000
--- a/demo/app/App_Resources/Android/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/background.png b/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/background.png
deleted file mode 100644
index eb381c2..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/background.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/icon.png b/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/icon.png
deleted file mode 100644
index 1034356..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/icon.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/logo.png b/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/logo.png
deleted file mode 100644
index 5218f4c..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-hdpi/logo.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/background.png b/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/background.png
deleted file mode 100644
index 748b2ad..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/background.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/icon.png b/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/icon.png
deleted file mode 100644
index ddfc17a..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/icon.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/logo.png b/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/logo.png
deleted file mode 100644
index b9e102a..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-ldpi/logo.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/background.png b/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/background.png
deleted file mode 100644
index efeaf29..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/background.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/icon.png b/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/icon.png
deleted file mode 100644
index 486e410..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/icon.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/logo.png b/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/logo.png
deleted file mode 100644
index 6263387..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-mdpi/logo.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-nodpi/splash_screen.xml b/demo/app/App_Resources/Android/src/main/res/drawable-nodpi/splash_screen.xml
deleted file mode 100644
index ada77f9..0000000
--- a/demo/app/App_Resources/Android/src/main/res/drawable-nodpi/splash_screen.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
- -
-
-
- -
-
-
-
\ No newline at end of file
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/background.png b/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/background.png
deleted file mode 100644
index 612bbd0..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/background.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/icon.png b/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/icon.png
deleted file mode 100644
index f291882..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/icon.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/logo.png b/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/logo.png
deleted file mode 100644
index ad8ee2f..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-xhdpi/logo.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/background.png b/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/background.png
deleted file mode 100644
index 0fa88e2..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/background.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/icon.png b/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/icon.png
deleted file mode 100644
index 4f69cb2..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/icon.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/logo.png b/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/logo.png
deleted file mode 100644
index 6683278..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-xxhdpi/logo.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/background.png b/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/background.png
deleted file mode 100644
index c650f64..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/background.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/icon.png b/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/icon.png
deleted file mode 100644
index 50887a8..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/icon.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/logo.png b/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/logo.png
deleted file mode 100644
index fa6331c..0000000
Binary files a/demo/app/App_Resources/Android/src/main/res/drawable-xxxhdpi/logo.png and /dev/null differ
diff --git a/demo/app/App_Resources/Android/src/main/res/values-v21/colors.xml b/demo/app/App_Resources/Android/src/main/res/values-v21/colors.xml
deleted file mode 100644
index a64641a..0000000
--- a/demo/app/App_Resources/Android/src/main/res/values-v21/colors.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
- #3d5afe
-
\ No newline at end of file
diff --git a/demo/app/App_Resources/Android/src/main/res/values-v21/styles.xml b/demo/app/App_Resources/Android/src/main/res/values-v21/styles.xml
deleted file mode 100644
index dac8727..0000000
--- a/demo/app/App_Resources/Android/src/main/res/values-v21/styles.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/demo/app/App_Resources/Android/src/main/res/values/colors.xml b/demo/app/App_Resources/Android/src/main/res/values/colors.xml
deleted file mode 100644
index 74ad882..0000000
--- a/demo/app/App_Resources/Android/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
- #F5F5F5
- #757575
- #33B5E5
- #272734
-
\ No newline at end of file
diff --git a/demo/app/App_Resources/Android/src/main/res/values/styles.xml b/demo/app/App_Resources/Android/src/main/res/values/styles.xml
deleted file mode 100644
index 1e8c7f2..0000000
--- a/demo/app/App_Resources/Android/src/main/res/values/styles.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json
deleted file mode 100644
index 5f53593..0000000
--- a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ /dev/null
@@ -1,128 +0,0 @@
-{
- "images" : [
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "icon-29.png",
- "scale" : "1x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "icon-29@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "icon-29@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "40x40",
- "idiom" : "iphone",
- "filename" : "icon-40@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "40x40",
- "idiom" : "iphone",
- "filename" : "icon-40@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "57x57",
- "idiom" : "iphone",
- "filename" : "icon-57.png",
- "scale" : "1x"
- },
- {
- "size" : "57x57",
- "idiom" : "iphone",
- "filename" : "icon-57@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "60x60",
- "idiom" : "iphone",
- "filename" : "icon-60@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "60x60",
- "idiom" : "iphone",
- "filename" : "icon-60@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "29x29",
- "idiom" : "ipad",
- "filename" : "icon-29.png",
- "scale" : "1x"
- },
- {
- "size" : "29x29",
- "idiom" : "ipad",
- "filename" : "icon-29@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "40x40",
- "idiom" : "ipad",
- "filename" : "icon-40.png",
- "scale" : "1x"
- },
- {
- "size" : "40x40",
- "idiom" : "ipad",
- "filename" : "icon-40@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "50x50",
- "idiom" : "ipad",
- "filename" : "icon-50.png",
- "scale" : "1x"
- },
- {
- "size" : "50x50",
- "idiom" : "ipad",
- "filename" : "icon-50@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "72x72",
- "idiom" : "ipad",
- "filename" : "icon-72.png",
- "scale" : "1x"
- },
- {
- "size" : "72x72",
- "idiom" : "ipad",
- "filename" : "icon-72@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "76x76",
- "idiom" : "ipad",
- "filename" : "icon-76.png",
- "scale" : "1x"
- },
- {
- "size" : "76x76",
- "idiom" : "ipad",
- "filename" : "icon-76@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "83.5x83.5",
- "idiom" : "ipad",
- "filename" : "icon-83.5@2x.png",
- "scale" : "2x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png
deleted file mode 100644
index 9e15af0..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
deleted file mode 100644
index 7b9e555..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
deleted file mode 100644
index 76f61ec..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png
deleted file mode 100644
index 15b06db..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
deleted file mode 100644
index 585065f..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png
deleted file mode 100644
index a450c42..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50.png
deleted file mode 100644
index 4a62478..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png
deleted file mode 100644
index 01ff7c1..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57.png
deleted file mode 100644
index beea819..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png
deleted file mode 100644
index c3dc7b0..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
deleted file mode 100644
index 457b6d9..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
deleted file mode 100644
index fa5a6ac..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72.png
deleted file mode 100644
index 556bdd6..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png
deleted file mode 100644
index 4f69cb2..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png
deleted file mode 100644
index 94abcf7..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
deleted file mode 100644
index 2e71dd3..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
deleted file mode 100644
index 4abc9ec..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/Contents.json b/demo/app/App_Resources/iOS/Assets.xcassets/Contents.json
deleted file mode 100644
index da4a164..0000000
--- a/demo/app/App_Resources/iOS/Assets.xcassets/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json
deleted file mode 100644
index 4414bad..0000000
--- a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json
+++ /dev/null
@@ -1,158 +0,0 @@
-{
- "images" : [
- {
- "extent" : "full-screen",
- "idiom" : "iphone",
- "subtype" : "736h",
- "filename" : "Default-736h@3x.png",
- "minimum-system-version" : "8.0",
- "orientation" : "portrait",
- "scale" : "3x"
- },
- {
- "extent" : "full-screen",
- "idiom" : "iphone",
- "subtype" : "736h",
- "filename" : "Default-Landscape@3x.png",
- "minimum-system-version" : "8.0",
- "orientation" : "landscape",
- "scale" : "3x"
- },
- {
- "extent" : "full-screen",
- "idiom" : "iphone",
- "subtype" : "667h",
- "filename" : "Default-667h@2x.png",
- "minimum-system-version" : "8.0",
- "orientation" : "portrait",
- "scale" : "2x"
- },
- {
- "orientation" : "portrait",
- "idiom" : "iphone",
- "filename" : "Default@2x.png",
- "extent" : "full-screen",
- "minimum-system-version" : "7.0",
- "scale" : "2x"
- },
- {
- "extent" : "full-screen",
- "idiom" : "iphone",
- "subtype" : "retina4",
- "filename" : "Default-568h@2x.png",
- "minimum-system-version" : "7.0",
- "orientation" : "portrait",
- "scale" : "2x"
- },
- {
- "orientation" : "portrait",
- "idiom" : "ipad",
- "filename" : "Default-Portrait.png",
- "extent" : "full-screen",
- "minimum-system-version" : "7.0",
- "scale" : "1x"
- },
- {
- "orientation" : "landscape",
- "idiom" : "ipad",
- "filename" : "Default-Landscape.png",
- "extent" : "full-screen",
- "minimum-system-version" : "7.0",
- "scale" : "1x"
- },
- {
- "orientation" : "portrait",
- "idiom" : "ipad",
- "filename" : "Default-Portrait@2x.png",
- "extent" : "full-screen",
- "minimum-system-version" : "7.0",
- "scale" : "2x"
- },
- {
- "orientation" : "landscape",
- "idiom" : "ipad",
- "filename" : "Default-Landscape@2x.png",
- "extent" : "full-screen",
- "minimum-system-version" : "7.0",
- "scale" : "2x"
- },
- {
- "orientation" : "portrait",
- "idiom" : "iphone",
- "filename" : "Default.png",
- "extent" : "full-screen",
- "scale" : "1x"
- },
- {
- "orientation" : "portrait",
- "idiom" : "iphone",
- "filename" : "Default@2x.png",
- "extent" : "full-screen",
- "scale" : "2x"
- },
- {
- "orientation" : "portrait",
- "idiom" : "iphone",
- "filename" : "Default-568h@2x.png",
- "extent" : "full-screen",
- "subtype" : "retina4",
- "scale" : "2x"
- },
- {
- "orientation" : "portrait",
- "idiom" : "ipad",
- "extent" : "to-status-bar",
- "scale" : "1x"
- },
- {
- "orientation" : "portrait",
- "idiom" : "ipad",
- "filename" : "Default-Portrait.png",
- "extent" : "full-screen",
- "scale" : "1x"
- },
- {
- "orientation" : "landscape",
- "idiom" : "ipad",
- "extent" : "to-status-bar",
- "scale" : "1x"
- },
- {
- "orientation" : "landscape",
- "idiom" : "ipad",
- "filename" : "Default-Landscape.png",
- "extent" : "full-screen",
- "scale" : "1x"
- },
- {
- "orientation" : "portrait",
- "idiom" : "ipad",
- "extent" : "to-status-bar",
- "scale" : "2x"
- },
- {
- "orientation" : "portrait",
- "idiom" : "ipad",
- "filename" : "Default-Portrait@2x.png",
- "extent" : "full-screen",
- "scale" : "2x"
- },
- {
- "orientation" : "landscape",
- "idiom" : "ipad",
- "extent" : "to-status-bar",
- "scale" : "2x"
- },
- {
- "orientation" : "landscape",
- "idiom" : "ipad",
- "filename" : "Default-Landscape@2x.png",
- "extent" : "full-screen",
- "scale" : "2x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png
deleted file mode 100644
index d7f17fc..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png
deleted file mode 100644
index b884154..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png
deleted file mode 100644
index faab4b6..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png
deleted file mode 100644
index 3365ba3..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png
deleted file mode 100644
index a44945c..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png
deleted file mode 100644
index e6dca62..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png
deleted file mode 100644
index 1a50079..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png
deleted file mode 100644
index 73d8b92..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png
deleted file mode 100644
index 9f1f6ce..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png
deleted file mode 100644
index 514fc5c..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json
deleted file mode 100644
index 4f4e9c5..0000000
--- a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "LaunchScreen-AspectFill.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "filename" : "LaunchScreen-AspectFill@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png
deleted file mode 100644
index c293f9c..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png
deleted file mode 100644
index 233693a..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json
deleted file mode 100644
index 23c0ffd..0000000
--- a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "LaunchScreen-Center.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "filename" : "LaunchScreen-Center@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png
deleted file mode 100644
index a5a775a..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png b/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png
deleted file mode 100644
index 154c193..0000000
Binary files a/demo/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png and /dev/null differ
diff --git a/demo/app/App_Resources/iOS/Info.plist b/demo/app/App_Resources/iOS/Info.plist
deleted file mode 100644
index ea3e3ea..0000000
--- a/demo/app/App_Resources/iOS/Info.plist
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- en
- CFBundleDisplayName
- ${PRODUCT_NAME}
- CFBundleExecutable
- ${EXECUTABLE_NAME}
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- ${PRODUCT_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- 1.0
- CFBundleSignature
- ????
- CFBundleVersion
- 1.0
- LSRequiresIPhoneOS
-
- UILaunchStoryboardName
- LaunchScreen
- UIRequiresFullScreen
-
- UIRequiredDeviceCapabilities
-
- armv7
-
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
-
-
diff --git a/demo/app/App_Resources/iOS/LaunchScreen.storyboard b/demo/app/App_Resources/iOS/LaunchScreen.storyboard
deleted file mode 100644
index 2ad9471..0000000
--- a/demo/app/App_Resources/iOS/LaunchScreen.storyboard
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/demo/app/App_Resources/iOS/build.xcconfig b/demo/app/App_Resources/iOS/build.xcconfig
deleted file mode 100644
index a777ac8..0000000
--- a/demo/app/App_Resources/iOS/build.xcconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-// You can add custom settings here
-// for example you can uncomment the following line to force distribution code signing
-// CODE_SIGN_IDENTITY = iPhone Distribution
-ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
-
-DEVELOPMENT_TEAM = 8Q5F6M3TNS
diff --git a/demo/app/app.css b/demo/app/app.css
deleted file mode 100644
index 5f28270..0000000
--- a/demo/app/app.css
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/demo/app/app.ts b/demo/app/app.ts
deleted file mode 100644
index deb50cb..0000000
--- a/demo/app/app.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import * as application from '@nativescript/core/application';
-import { knownFolders, path } from '@nativescript/core/file-system';
-import * as Https from '@nativescript-community/https';
-Https.setCache({
- diskLocation: path.join(knownFolders.documents().path, 'httpcache'),
- diskSize: 10 * 1024 * 1024, // 10 MiB
-});
-application.run({ moduleName: 'main-page' });
diff --git a/demo/app/main-page.ts b/demo/app/main-page.ts
deleted file mode 100644
index 6c393cc..0000000
--- a/demo/app/main-page.ts
+++ /dev/null
@@ -1,159 +0,0 @@
-import * as Https from '@nativescript-community/https';
-import * as Observable from '@nativescript/core/data/observable';
-import * as fs from '@nativescript/core/file-system';
-import * as dialogs from '@nativescript/core/ui/dialogs';
-import * as Page from '@nativescript/core/ui/page';
-
-let page;
-let viewModel;
-export function pageLoaded(args: Page.NavigatedData) {
- page = args.object as Page.Page;
- viewModel = Observable.fromObject({
- enabled: false,
- progress: 0,
- currentRequest: null,
- });
- page.bindingContext = viewModel;
-}
-
-function createRequest(url: string, options?: Partial) {
- return Https.createRequest({
- useLegacy: true,
- url,
- method: 'GET',
- timeout: 1,
- ...options,
- });
-}
-
-function onError(error) {
- console.error('Https.request error', error, error.stack);
- dialogs.alert(error.toString());
- page.bindingContext.currentRequest = null;
- page.bindingContext.progress = 0;
- return Promise.reject(error);
-}
-function getRequest(url: string, options?: Partial) {
- return Https.request({
- useLegacy: true,
- url,
- method: 'GET',
- timeout: 1,
- ...options,
- })
- .then((response) => {
- page.bindingContext.currentRequest = null;
- page.bindingContext.progress = 0;
- console.log('Https.request response', response);
- return response;
- })
- .catch(onError);
-}
-
-function postRequest(url: string, options?: Partial) {
- return Https.request({
- useLegacy: true,
- url,
- method: 'POST',
- ...options,
- })
- .then((response) => console.log('Https.request response', response))
- .catch((error) => {
- console.error('Https.request error', error);
- dialogs.alert(error);
- });
-}
-
-export function postHttpbin() {
- postRequest('https://httpbin.org/post', {
- body: { foo: 'bar', baz: undefined, plaz: null },
- });
-}
-
-export function postHttpbinWithUTF8() {
- Https.request({
- url: 'https://httpbin.org/post',
- method: 'POST',
- body: { foo: 'bar', baz: undefined, plaz: null },
- headers: {
- 'Content-Type': 'application/json; charset=utf-8',
- 'X-testing': 'ok',
- },
- }).catch((error) => {
- console.error('Https.request error', error);
- dialogs.alert(error);
- });
-}
-
-export function getHttpbin() {
- getRequest('https://httpbin.org/get', {
- headers: {
- // 'Cache-Control': 'public, only-if-cached, max-stale=' +(60 * 60 * 24 * 7),
- 'Cache-Control': 'max-age=50000',
- }
- });
-}
-
-export function cancelCurrentRequest() {
- if (page.bindingContext.currentRequest) {
- page.bindingContext.currentRequest.cancel();
- }
-}
-export function getBigFile() {
- const request = createRequest('http://ipv4.download.thinkbroadband.com/200MB.zip', {
- onProgress: (current, total) => {
- page.bindingContext.progress = (current / total) * 100;
- },
- });
- page.bindingContext.currentRequest = request;
-
- return new Promise((resolve, reject) => {
- request.run(resolve, reject);
- })
- .then((response) => {
- console.log('did get response');
- const dir = fs.knownFolders.temp().getFile('200MB.zip');
- return (response.content as Https.HttpsResponseLegacy).toFile(dir.path);
- // console.log("did get response done");
- })
- .then(() => {
- page.bindingContext.currentPromise = null;
- console.log('did get response done');
- })
- .catch(onError);
-}
-
-export function getHttpbinLargeResponse() {
- getRequest('https://httpbin.org/bytes/100000');
-}
-
-export function getMockbin() {
- getRequest('https://mockbin.com/request');
-}
-
-export function get404() {
- getRequest('https://mockbin.com/reque2st');
-}
-
-export function enableSSLPinning(args: Observable.EventData) {
- const dir = fs.knownFolders.currentApp().getFolder('assets');
- const certificate = dir.getFile('httpbin.org.cer').path;
- Https.enableSSLPinning({
- host: 'httpbin.org',
- commonName: 'httpbin.org',
- certificate,
- });
- console.log('enabled');
-}
-
-export function enableSSLPinningExpired(args: Observable.EventData) {
- const dir = fs.knownFolders.currentApp().getFolder('assets');
- const certificate = dir.getFile('httpbin.org.expired.cer').path;
- Https.enableSSLPinning({ host: 'httpbin.org', certificate });
- console.log('enabled');
-}
-
-export function disableSSLPinning(args: Observable.EventData) {
- Https.disableSSLPinning();
- console.log('disabled');
-}
diff --git a/demo/app/main-page.xml b/demo/app/main-page.xml
deleted file mode 100644
index d6f4e68..0000000
--- a/demo/app/main-page.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/demo/nativescript.config.ts b/demo/nativescript.config.ts
deleted file mode 100644
index 8eb96e6..0000000
--- a/demo/nativescript.config.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { NativeScriptConfig } from '@nativescript/core';
-
-export default {
- id: 'org.nativescript.plugindemo.https',
- appResourcesPath: 'app/App_Resources',
- android: {
- v8Flags: '--expose_gc',
- markingMode: 'none',
- requireModules: {
- 0: 'nativescript-https',
- },
- },
- appPath: 'app',
-} as NativeScriptConfig;
diff --git a/demo/package.json b/demo/package.json
deleted file mode 100644
index a47173d..0000000
--- a/demo/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "dependencies": {
- "@nativescript-community/https": "file:../plugin",
- "@nativescript/core": "7.2.0",
- "@nativescript/webpack": "4.1.0",
- "nativescript-theme-core": "^2.0.24",
- "nativescript-unit-test-runner": "0.7.0"
- },
- "devDependencies": {
- "@nativescript/android": "7.0.1",
- "@nativescript/types": "7.0.0",
- "nativescript-css-loader": "~0.26.1",
- "typescript": "3.9.7"
- },
- "scripts": {
- "build.plugin": "cd ../src && npm run build",
- "ci.tslint": "npm i && tslint --config '../tslint.json' 'app/**/*.ts' --exclude '**/node_modules/**'"
- },
- "main": "app.js"
-}
diff --git a/demo/references.d.ts b/demo/references.d.ts
deleted file mode 100644
index e69de29..0000000
diff --git a/demo/tsconfig.json b/demo/tsconfig.json
deleted file mode 100644
index 6f16f6f..0000000
--- a/demo/tsconfig.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
- "compilerOptions": {
- "target": "es2017",
- "module": "esnext",
- "declaration": false,
- "removeComments": false,
- "noLib": false,
- "emitDecoratorMetadata": true,
- "experimentalDecorators": true,
- "lib": [
- "es6",
- "dom",
- "es2017"
- ],
- "pretty": true,
- "allowUnreachableCode": false,
- "allowUnusedLabels": false,
- "noEmitHelpers": true,
- "noEmitOnError": false,
- "noImplicitAny": false,
- "noImplicitReturns": true,
- "noImplicitUseStrict": false,
- "noFallthroughCasesInSwitch": true,
- "baseUrl": ".",
- "paths": {
- "*": [
- "./node_modules/*"
- ],
- "~/*": [
- "app/*"
- ]
- },
- "moduleResolution": "node"
- },
- "include": [
- "**/*"
- ],
- "exclude": [
- "node_modules",
- "platforms"
- ],
- "compileOnSave": false
-}
\ No newline at end of file
diff --git a/demo/webpack.config.js b/demo/webpack.config.js
deleted file mode 100644
index 379ca48..0000000
--- a/demo/webpack.config.js
+++ /dev/null
@@ -1,332 +0,0 @@
-const { join, relative, resolve, sep } = require('path');
-const fs = require('fs');
-
-const webpack = require('webpack');
-const nsWebpack = require('@nativescript/webpack');
-const nativescriptTarget = require('@nativescript/webpack/nativescript-target');
-const { getNoEmitOnErrorFromTSConfig } = require('@nativescript/webpack/utils/tsconfig-utils');
-const { CleanWebpackPlugin } = require('clean-webpack-plugin');
-const CopyWebpackPlugin = require('copy-webpack-plugin');
-const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
-const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
-const { NativeScriptWorkerPlugin } = require('nativescript-worker-loader/NativeScriptWorkerPlugin');
-const TerserPlugin = require('terser-webpack-plugin');
-const hashSalt = Date.now().toString();
-
-module.exports = (env) => {
- const platform = env && ((env.android && 'android') || (env.ios && 'ios') || env.platform);
- if (!platform) {
- throw new Error('You need to provide a target platform!');
- }
-
- const platforms = ['ios', 'android'];
- const projectRoot = __dirname;
-
- if (env.platform) {
- platforms.push(env.platform);
- }
-
- // Default destination inside platforms//...
- const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
-
- const {
- // The 'appPath' and 'appResourcesPath' values are fetched from
- // the nsconfig.json configuration file.
- appPath = 'src',
- appResourcesPath = 'App_Resources',
-
- // You can provide the following flags when running 'tns run android|ios'
- snapshot, // --env.snapshot
- production, // --env.production
- uglify, // --env.uglify
- report, // --env.report
- sourceMap, // --env.sourceMap
- hiddenSourceMap, // --env.hiddenSourceMap
- hmr, // --env.hmr,
- unitTesting, // --env.unitTesting,
- testing, // --env.testing
- verbose, // --env.verbose
- ci, // --env.ci
- snapshotInDocker, // --env.snapshotInDocker
- skipSnapshotTools, // --env.skipSnapshotTools
- compileSnapshot, // --env.compileSnapshot
- appComponents = [],
- entries = {},
- } = env;
-
- const useLibs = compileSnapshot;
- const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap;
- const externals = nsWebpack.getConvertedExternals(env.externals);
-
- let appFullPath = resolve(projectRoot, appPath);
- if (!fs.existsSync(appFullPath)) {
- // some apps use 'app' directory
- appFullPath = resolve(projectRoot, 'app');
- }
- const hasRootLevelScopedModules = nsWebpack.hasRootLevelScopedModules({ projectDir: projectRoot });
- let coreModulesPackageName = 'tns-core-modules';
- const alias = env.alias || {};
- alias['~/package.json'] = resolve(projectRoot, 'package.json');
- alias['~'] = appFullPath;
-
- if (hasRootLevelScopedModules) {
- coreModulesPackageName = '@nativescript/core';
- alias['tns-core-modules'] = coreModulesPackageName;
- }
- const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
-
- const copyIgnore = { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] };
-
- const entryModule = nsWebpack.getEntryModule(appFullPath, platform);
- const entryPath = `.${sep}${entryModule}.ts`;
- Object.assign(entries, { bundle: entryPath }, entries);
-
- const tsConfigPath = resolve(projectRoot, 'tsconfig.json');
-
- const areCoreModulesExternal = Array.isArray(env.externals) && env.externals.some((e) => e.indexOf('@nativescript') > -1);
- if (platform === 'ios' && !areCoreModulesExternal && !testing) {
- entries['tns_modules/inspector_modules'] = '@nativescript/core/inspector_modules';
- }
-
- let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist);
-
- const itemsToClean = [`${dist}/**/*`];
- if (platform === 'android') {
- itemsToClean.push(`${join(projectRoot, 'platforms', 'android', 'app', 'src', 'main', 'assets', 'snapshots')}`);
- itemsToClean.push(`${join(projectRoot, 'platforms', 'android', 'app', 'build', 'configurations', 'nativescript-android-snapshot')}`);
- }
-
- const noEmitOnErrorFromTSConfig = getNoEmitOnErrorFromTSConfig(tsConfigPath);
-
- // Add your custom Activities, Services and other android app components here.
- appComponents.push('@nativescript/core/ui/frame', '@nativescript/core/ui/frame/activity');
-
- nsWebpack.processAppComponents(appComponents, platform);
- const config = {
- mode: production ? 'production' : 'development',
- context: appFullPath,
- externals,
- watchOptions: {
- ignored: [
- appResourcesFullPath,
- // Don't watch hidden files
- '**/.*',
- ],
- },
- target: nativescriptTarget,
- entry: entries,
- output: {
- pathinfo: false,
- path: dist,
- sourceMapFilename,
- libraryTarget: 'commonjs2',
- filename: '[name].js',
- globalObject: 'global',
- hashSalt,
- },
- resolve: {
- extensions: ['.ts', '.js', '.scss', '.css'],
- // Resolve {N} system modules from @nativescript/core
- modules: [resolve(__dirname, `node_modules/${coreModulesPackageName}`), resolve(__dirname, 'node_modules'), `node_modules/${coreModulesPackageName}`, 'node_modules'],
- alias,
- // resolve symlinks to symlinked modules
- symlinks: true,
- },
- resolveLoader: {
- // don't resolve symlinks to symlinked loaders
- symlinks: false,
- },
- node: {
- // Disable node shims that conflict with NativeScript
- http: false,
- timers: false,
- setImmediate: false,
- fs: 'empty',
- __dirname: false,
- },
- devtool: hiddenSourceMap ? 'hidden-source-map' : sourceMap ? 'inline-source-map' : 'none',
- optimization: {
- runtimeChunk: 'single',
- noEmitOnErrors: noEmitOnErrorFromTSConfig,
- splitChunks: {
- cacheGroups: {
- vendor: {
- name: 'vendor',
- chunks: 'all',
- test: (module, chunks) => {
- const moduleName = module.nameForCondition ? module.nameForCondition() : '';
- return /[\\/]node_modules[\\/]/.test(moduleName) || appComponents.some((comp) => comp === moduleName);
- },
- enforce: true,
- },
- },
- },
- minimize: !!uglify,
- minimizer: [
- new TerserPlugin({
- parallel: true,
- cache: !ci,
- sourceMap: isAnySourceMapEnabled,
- terserOptions: {
- output: {
- comments: false,
- semicolons: !isAnySourceMapEnabled,
- },
- compress: {
- // The Android SBG has problems parsing the output
- // when these options are enabled
- collapse_vars: platform !== 'android',
- sequences: platform !== 'android',
- // For v8 Compatibility
- keep_infinity: true, // for V8
- reduce_funcs: false, // for V8
- // custom
- drop_console: production,
- drop_debugger: true,
- global_defs: {
- __UGLIFIED__: true,
- },
- },
- // Required for Element Level CSS, Observable Events, & Android Frame
- keep_classnames: true,
- },
- }),
- ],
- },
- module: {
- rules: [
- {
- include: join(appFullPath, entryPath),
- use: [
- // Require all Android app components
- platform === 'android' && {
- loader: '@nativescript/webpack/helpers/android-app-components-loader',
- options: { modules: appComponents },
- },
-
- {
- loader: '@nativescript/webpack/bundle-config-loader',
- options: {
- loadCss: !snapshot, // load the application css if in debug mode
- unitTesting,
- appFullPath,
- projectRoot,
- ignoredFiles: nsWebpack.getUserDefinedEntries(entries, platform),
- },
- },
- ].filter((loader) => !!loader),
- },
-
- {
- test: /\.(ts|css|scss|html|xml)$/,
- use: '@nativescript/webpack/hmr/hot-loader',
- },
-
- { test: /\.(html|xml)$/, use: '@nativescript/webpack/helpers/xml-namespace-loader' },
-
- {
- test: /\.css$/,
- use: '@nativescript/webpack/helpers/css2json-loader',
- },
-
- {
- test: /\.scss$/,
- use: ['@nativescript/webpack/helpers/css2json-loader', 'sass-loader'],
- },
-
- {
- test: /\.ts$/,
- use: {
- loader: 'ts-loader',
- options: {
- configFile: tsConfigPath,
- // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#faster-builds
- // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#hot-module-replacement
- transpileOnly: true,
- allowTsInNodeModules: true,
- compilerOptions: {
- sourceMap: isAnySourceMapEnabled,
- declaration: false,
- },
- getCustomTransformers: (program) => ({
- before: [require('@nativescript/webpack/transformers/ns-transform-native-classes').default],
- }),
- },
- },
- },
- ],
- },
- plugins: [
- // Define useful constants like TNS_WEBPACK
- new webpack.DefinePlugin({
- 'global.TNS_WEBPACK': 'true',
- 'global.isAndroid': platform === 'android',
- 'global.isIOS': platform === 'ios',
- process: 'global.process',
- }),
- // Remove all files from the out dir.
- new CleanWebpackPlugin({
- cleanOnceBeforeBuildPatterns: itemsToClean,
- verbose: !!verbose,
- }),
- // Copy assets
- new CopyWebpackPlugin([{ from: { glob: 'assets/**', dot: false } }, { from: { glob: 'fonts/**', dot: false } }, { from: { glob: '**/*.jpg', dot: false } }, { from: { glob: '**/*.png', dot: false } }], copyIgnore),
- new nsWebpack.GenerateNativeScriptEntryPointsPlugin('bundle'),
- // For instructions on how to set up workers with webpack
- // check out https://github.com/nativescript/worker-loader
- new NativeScriptWorkerPlugin(),
- new nsWebpack.PlatformFSPlugin({
- platform,
- platforms,
- }),
- // Does IPC communication with the {N} CLI to notify events when running in watch mode.
- new nsWebpack.WatchStateLoggerPlugin(),
- // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#faster-builds
- // https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#hot-module-replacement
- new ForkTsCheckerWebpackPlugin({
- async: false,
- typescript: {
- configFile: tsConfigPath,
- memoryLimit: 4096,
- diagnosticOptions: {
- syntactic: true,
- semantic: true,
- },
- },
- }),
- ],
- };
-
- if (report) {
- // Generate report files for bundles content
- config.plugins.push(
- new BundleAnalyzerPlugin({
- analyzerMode: 'static',
- openAnalyzer: false,
- generateStatsFile: true,
- reportFilename: resolve(projectRoot, 'report', `report.html`),
- statsFilename: resolve(projectRoot, 'report', `stats.json`),
- })
- );
- }
-
- if (snapshot) {
- config.plugins.push(
- new nsWebpack.NativeScriptSnapshotPlugin({
- chunk: 'vendor',
- requireModules: ['@nativescript/core/bundle-entry-points'],
- projectRoot,
- webpackConfig: config,
- snapshotInDocker,
- skipSnapshotTools,
- useLibs,
- })
- );
- }
-
- if (hmr) {
- config.plugins.push(new webpack.HotModuleReplacementPlugin());
- }
-
- return config;
-};
diff --git a/docs/.nojekyll b/docs/.nojekyll
new file mode 100644
index 0000000..e2ac661
--- /dev/null
+++ b/docs/.nojekyll
@@ -0,0 +1 @@
+TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false.
\ No newline at end of file
diff --git a/docs/assets/hierarchy.js b/docs/assets/hierarchy.js
new file mode 100644
index 0000000..fb85f0a
--- /dev/null
+++ b/docs/assets/hierarchy.js
@@ -0,0 +1 @@
+window.hierarchyData = "eJyrVirKzy8pVrKKjtVRKkpNy0lNLsnMzytWsqqurQUAmx4Kpg=="
\ No newline at end of file
diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css
new file mode 100644
index 0000000..f9466b6
--- /dev/null
+++ b/docs/assets/highlight.css
@@ -0,0 +1,92 @@
+:root {
+ --light-hl-0: #795E26;
+ --dark-hl-0: #DCDCAA;
+ --light-hl-1: #000000;
+ --dark-hl-1: #D4D4D4;
+ --light-hl-2: #A31515;
+ --dark-hl-2: #CE9178;
+ --light-hl-3: #AF00DB;
+ --dark-hl-3: #CE92A4;
+ --light-hl-4: #0000FF;
+ --dark-hl-4: #569CD6;
+ --light-hl-5: #001080;
+ --dark-hl-5: #9CDCFE;
+ --light-hl-6: #098658;
+ --dark-hl-6: #B5CEA8;
+ --light-hl-7: #008000;
+ --dark-hl-7: #6A9955;
+ --light-hl-8: #000000;
+ --dark-hl-8: #C8C8C8;
+ --light-hl-9: #267F99;
+ --dark-hl-9: #4EC9B0;
+ --light-code-background: #FFFFFF;
+ --dark-code-background: #1E1E1E;
+}
+
+@media (prefers-color-scheme: light) { :root {
+ --hl-0: var(--light-hl-0);
+ --hl-1: var(--light-hl-1);
+ --hl-2: var(--light-hl-2);
+ --hl-3: var(--light-hl-3);
+ --hl-4: var(--light-hl-4);
+ --hl-5: var(--light-hl-5);
+ --hl-6: var(--light-hl-6);
+ --hl-7: var(--light-hl-7);
+ --hl-8: var(--light-hl-8);
+ --hl-9: var(--light-hl-9);
+ --code-background: var(--light-code-background);
+} }
+
+@media (prefers-color-scheme: dark) { :root {
+ --hl-0: var(--dark-hl-0);
+ --hl-1: var(--dark-hl-1);
+ --hl-2: var(--dark-hl-2);
+ --hl-3: var(--dark-hl-3);
+ --hl-4: var(--dark-hl-4);
+ --hl-5: var(--dark-hl-5);
+ --hl-6: var(--dark-hl-6);
+ --hl-7: var(--dark-hl-7);
+ --hl-8: var(--dark-hl-8);
+ --hl-9: var(--dark-hl-9);
+ --code-background: var(--dark-code-background);
+} }
+
+:root[data-theme='light'] {
+ --hl-0: var(--light-hl-0);
+ --hl-1: var(--light-hl-1);
+ --hl-2: var(--light-hl-2);
+ --hl-3: var(--light-hl-3);
+ --hl-4: var(--light-hl-4);
+ --hl-5: var(--light-hl-5);
+ --hl-6: var(--light-hl-6);
+ --hl-7: var(--light-hl-7);
+ --hl-8: var(--light-hl-8);
+ --hl-9: var(--light-hl-9);
+ --code-background: var(--light-code-background);
+}
+
+:root[data-theme='dark'] {
+ --hl-0: var(--dark-hl-0);
+ --hl-1: var(--dark-hl-1);
+ --hl-2: var(--dark-hl-2);
+ --hl-3: var(--dark-hl-3);
+ --hl-4: var(--dark-hl-4);
+ --hl-5: var(--dark-hl-5);
+ --hl-6: var(--dark-hl-6);
+ --hl-7: var(--dark-hl-7);
+ --hl-8: var(--dark-hl-8);
+ --hl-9: var(--dark-hl-9);
+ --code-background: var(--dark-code-background);
+}
+
+.hl-0 { color: var(--hl-0); }
+.hl-1 { color: var(--hl-1); }
+.hl-2 { color: var(--hl-2); }
+.hl-3 { color: var(--hl-3); }
+.hl-4 { color: var(--hl-4); }
+.hl-5 { color: var(--hl-5); }
+.hl-6 { color: var(--hl-6); }
+.hl-7 { color: var(--hl-7); }
+.hl-8 { color: var(--hl-8); }
+.hl-9 { color: var(--hl-9); }
+pre, code { background: var(--code-background); }
diff --git a/docs/assets/icons.js b/docs/assets/icons.js
new file mode 100644
index 0000000..58882d7
--- /dev/null
+++ b/docs/assets/icons.js
@@ -0,0 +1,18 @@
+(function() {
+ addIcons();
+ function addIcons() {
+ if (document.readyState === "loading") return document.addEventListener("DOMContentLoaded", addIcons);
+ const svg = document.body.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg"));
+ svg.innerHTML = `M M N E P V F C I C P M F P C P T T A A A T R `;
+ svg.style.display = "none";
+ if (location.protocol === "file:") updateUseElements();
+ }
+
+ function updateUseElements() {
+ document.querySelectorAll("use").forEach(el => {
+ if (el.getAttribute("href").includes("#icon-")) {
+ el.setAttribute("href", el.getAttribute("href").replace(/.*#/, "#"));
+ }
+ });
+ }
+})()
\ No newline at end of file
diff --git a/docs/assets/icons.svg b/docs/assets/icons.svg
new file mode 100644
index 0000000..50ad579
--- /dev/null
+++ b/docs/assets/icons.svg
@@ -0,0 +1 @@
+M M N E P V F C I C P M F P C P T T A A A T R
\ No newline at end of file
diff --git a/docs/assets/main.js b/docs/assets/main.js
new file mode 100644
index 0000000..64b80ab
--- /dev/null
+++ b/docs/assets/main.js
@@ -0,0 +1,60 @@
+"use strict";
+window.translations={"copy":"Copy","copied":"Copied!","normally_hidden":"This member is normally hidden due to your filter settings.","hierarchy_expand":"Expand","hierarchy_collapse":"Collapse","folder":"Folder","search_index_not_available":"The search index is not available","search_no_results_found_for_0":"No results found for {0}","kind_1":"Project","kind_2":"Module","kind_4":"Namespace","kind_8":"Enumeration","kind_16":"Enumeration Member","kind_32":"Variable","kind_64":"Function","kind_128":"Class","kind_256":"Interface","kind_512":"Constructor","kind_1024":"Property","kind_2048":"Method","kind_4096":"Call Signature","kind_8192":"Index Signature","kind_16384":"Constructor Signature","kind_32768":"Parameter","kind_65536":"Type Literal","kind_131072":"Type Parameter","kind_262144":"Accessor","kind_524288":"Get Signature","kind_1048576":"Set Signature","kind_2097152":"Type Alias","kind_4194304":"Reference","kind_8388608":"Document"};
+"use strict";(()=>{var Ke=Object.create;var he=Object.defineProperty;var Ge=Object.getOwnPropertyDescriptor;var Ze=Object.getOwnPropertyNames;var Xe=Object.getPrototypeOf,Ye=Object.prototype.hasOwnProperty;var et=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var tt=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ze(e))!Ye.call(t,i)&&i!==n&&he(t,i,{get:()=>e[i],enumerable:!(r=Ge(e,i))||r.enumerable});return t};var nt=(t,e,n)=>(n=t!=null?Ke(Xe(t)):{},tt(e||!t||!t.__esModule?he(n,"default",{value:t,enumerable:!0}):n,t));var ye=et((me,ge)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=(function(e){return function(n){e.console&&console.warn&&console.warn(n)}})(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var d=t.utils.clone(n)||{};d.position=[a,l],d.index=s.length,s.push(new t.Token(r.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index.
+`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(oc?d+=2:a==c&&(n+=r[l+1]*i[d+1],l+=2,d+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var c=s.node.edges["*"];else{var c=new t.TokenSet;s.node.edges["*"]=c}if(s.str.length==0&&(c.final=!0),i.push({node:c,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}s.str.length==1&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),f=s.str.charAt(1),p;f in s.node.edges?p=s.node.edges[f]:(p=new t.TokenSet,s.node.edges[f]=p),s.str.length==1&&(p.final=!0),i.push({node:p,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),c=0;c1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},(function(e,n){typeof define=="function"&&define.amd?define(n):typeof me=="object"?ge.exports=n():e.lunr=n()})(this,function(){return t})})()});var M,G={getItem(){return null},setItem(){}},K;try{K=localStorage,M=K}catch{K=G,M=G}var S={getItem:t=>M.getItem(t),setItem:(t,e)=>M.setItem(t,e),disableWritingLocalStorage(){M=G},disable(){localStorage.clear(),M=G},enable(){M=K}};window.TypeDoc||={disableWritingLocalStorage(){S.disableWritingLocalStorage()},disableLocalStorage:()=>{S.disable()},enableLocalStorage:()=>{S.enable()}};window.translations||={copy:"Copy",copied:"Copied!",normally_hidden:"This member is normally hidden due to your filter settings.",hierarchy_expand:"Expand",hierarchy_collapse:"Collapse",search_index_not_available:"The search index is not available",search_no_results_found_for_0:"No results found for {0}",folder:"Folder",kind_1:"Project",kind_2:"Module",kind_4:"Namespace",kind_8:"Enumeration",kind_16:"Enumeration Member",kind_32:"Variable",kind_64:"Function",kind_128:"Class",kind_256:"Interface",kind_512:"Constructor",kind_1024:"Property",kind_2048:"Method",kind_4096:"Call Signature",kind_8192:"Index Signature",kind_16384:"Constructor Signature",kind_32768:"Parameter",kind_65536:"Type Literal",kind_131072:"Type Parameter",kind_262144:"Accessor",kind_524288:"Get Signature",kind_1048576:"Set Signature",kind_2097152:"Type Alias",kind_4194304:"Reference",kind_8388608:"Document"};var pe=[];function X(t,e){pe.push({selector:e,constructor:t})}var Z=class{alwaysVisibleMember=null;constructor(){this.createComponents(document.body),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible()),document.body.style.display||(this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}createComponents(e){pe.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}showPage(){document.body.style.display&&(document.body.style.removeProperty("display"),this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}scrollToHash(){if(location.hash){let e=document.getElementById(location.hash.substring(1));if(!e)return;e.scrollIntoView({behavior:"instant",block:"start"})}}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),n=e?.parentElement;for(;n&&!n.classList.contains(".tsd-navigation");)n instanceof HTMLDetailsElement&&(n.open=!0),n=n.parentElement;if(e&&!rt(e)){let r=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=r,document.querySelector(".col-sidebar").scrollTop=r}}updateIndexVisibility(){let e=document.querySelector(".tsd-index-content"),n=e?.open;e&&(e.open=!0),document.querySelectorAll(".tsd-index-section").forEach(r=>{r.style.display="block";let i=Array.from(r.querySelectorAll(".tsd-index-link")).every(s=>s.offsetParent==null);r.style.display=i?"none":"block"}),e&&(e.open=n)}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(!n)return;let r=n.offsetParent==null,i=n;for(;i!==document.body;)i instanceof HTMLDetailsElement&&(i.open=!0),i=i.parentElement;if(n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let s=document.createElement("p");s.classList.add("warning"),s.textContent=window.translations.normally_hidden,n.prepend(s)}r&&e.scrollIntoView()}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let n;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent=window.translations.copied,e.classList.add("visible"),clearTimeout(n),n=setTimeout(()=>{e.classList.remove("visible"),n=setTimeout(()=>{e.textContent=window.translations.copy},100)},1e3)})})}};function rt(t){let e=t.getBoundingClientRect(),n=Math.max(document.documentElement.clientHeight,window.innerHeight);return!(e.bottom<0||e.top-n>=0)}var fe=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var Ie=nt(ye(),1);async function R(t){let e=Uint8Array.from(atob(t),s=>s.charCodeAt(0)),r=new Blob([e]).stream().pipeThrough(new DecompressionStream("deflate")),i=await new Response(r).text();return JSON.parse(i)}var Y="closing",ae="tsd-overlay";function it(){let t=Math.abs(window.innerWidth-document.documentElement.clientWidth);document.body.style.overflow="hidden",document.body.style.paddingRight=`${t}px`}function st(){document.body.style.removeProperty("overflow"),document.body.style.removeProperty("padding-right")}function xe(t,e){t.addEventListener("animationend",()=>{t.classList.contains(Y)&&(t.classList.remove(Y),document.getElementById(ae)?.remove(),t.close(),st())}),t.addEventListener("cancel",n=>{n.preventDefault(),ve(t)}),e?.closeOnClick&&document.addEventListener("click",n=>{t.open&&!t.contains(n.target)&&ve(t)},!0)}function Ee(t){if(t.open)return;let e=document.createElement("div");e.id=ae,document.body.appendChild(e),t.showModal(),it()}function ve(t){if(!t.open)return;document.getElementById(ae)?.classList.add(Y),t.classList.add(Y)}var I=class{el;app;constructor(e){this.el=e.el,this.app=e.app}};var be=document.head.appendChild(document.createElement("style"));be.dataset.for="filters";var le={};function we(t){for(let e of t.split(/\s+/))if(le.hasOwnProperty(e)&&!le[e])return!0;return!1}var ee=class extends I{key;value;constructor(e){super(e),this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),be.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; }
+`,this.app.updateIndexVisibility()}fromLocalStorage(){let e=S.getItem(this.key);return e?e==="true":this.el.checked}setLocalStorage(e){S.setItem(this.key,e.toString()),this.value=e,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),le[`tsd-is-${this.el.name}`]=this.value,this.app.filterChanged(),this.app.updateIndexVisibility()}};var Le=0;async function Se(t,e){if(!window.searchData)return;let n=await R(window.searchData);t.data=n,t.index=Ie.Index.load(n.index),e.innerHTML=""}function _e(){let t=document.getElementById("tsd-search-trigger"),e=document.getElementById("tsd-search"),n=document.getElementById("tsd-search-input"),r=document.getElementById("tsd-search-results"),i=document.getElementById("tsd-search-script"),s=document.getElementById("tsd-search-status");if(!(t&&e&&n&&r&&i&&s))throw new Error("Search controls missing");let o={base:document.documentElement.dataset.base};o.base.endsWith("/")||(o.base+="/"),i.addEventListener("error",()=>{let a=window.translations.search_index_not_available;Pe(s,a)}),i.addEventListener("load",()=>{Se(o,s)}),Se(o,s),ot({trigger:t,searchEl:e,results:r,field:n,status:s},o)}function ot(t,e){let{field:n,results:r,searchEl:i,status:s,trigger:o}=t;xe(i,{closeOnClick:!0});function a(){Ee(i),n.setSelectionRange(0,n.value.length)}o.addEventListener("click",a),n.addEventListener("input",fe(()=>{at(r,n,s,e)},200)),n.addEventListener("keydown",l=>{if(r.childElementCount===0||l.ctrlKey||l.metaKey||l.altKey)return;let d=n.getAttribute("aria-activedescendant"),f=d?document.getElementById(d):null;if(f){let p=!1,v=!1;switch(l.key){case"Home":case"End":case"ArrowLeft":case"ArrowRight":v=!0;break;case"ArrowDown":case"ArrowUp":p=l.shiftKey;break}(p||v)&&ke(n)}if(!l.shiftKey)switch(l.key){case"Enter":f?.querySelector("a")?.click();break;case"ArrowUp":Te(r,n,f,-1),l.preventDefault();break;case"ArrowDown":Te(r,n,f,1),l.preventDefault();break}});function c(){ke(n)}n.addEventListener("change",c),n.addEventListener("blur",c),n.addEventListener("click",c),document.body.addEventListener("keydown",l=>{if(l.altKey||l.metaKey||l.shiftKey)return;let d=l.ctrlKey&&l.key==="k",f=!l.ctrlKey&&!ut()&&l.key==="/";(d||f)&&(l.preventDefault(),a())})}function at(t,e,n,r){if(!r.index||!r.data)return;t.innerHTML="",n.innerHTML="",Le+=1;let i=e.value.trim(),s;if(i){let a=i.split(" ").map(c=>c.length?`*${c}*`:"").join(" ");s=r.index.search(a).filter(({ref:c})=>{let l=r.data.rows[Number(c)].classes;return!l||!we(l)})}else s=[];if(s.length===0&&i){let a=window.translations.search_no_results_found_for_0.replace("{0}",` "${te(i)} " `);Pe(n,a);return}for(let a=0;ac.score-a.score);let o=Math.min(10,s.length);for(let a=0;a `,f=Ce(c.name,i);globalThis.DEBUG_SEARCH_WEIGHTS&&(f+=` (score: ${s[a].score.toFixed(2)})`),c.parent&&(f=`
+ ${Ce(c.parent,i)}. ${f}`);let p=document.createElement("li");p.id=`tsd-search:${Le}-${a}`,p.role="option",p.ariaSelected="false",p.classList.value=c.classes??"";let v=document.createElement("a");v.tabIndex=-1,v.href=r.base+c.url,v.innerHTML=d+`${f} `,p.append(v),t.appendChild(p)}}function Te(t,e,n,r){let i;if(r===1?i=n?.nextElementSibling||t.firstElementChild:i=n?.previousElementSibling||t.lastElementChild,i!==n){if(!i||i.role!=="option"){console.error("Option missing");return}i.ariaSelected="true",i.scrollIntoView({behavior:"smooth",block:"nearest"}),e.setAttribute("aria-activedescendant",i.id),n?.setAttribute("aria-selected","false")}}function ke(t){let e=t.getAttribute("aria-activedescendant");(e?document.getElementById(e):null)?.setAttribute("aria-selected","false"),t.setAttribute("aria-activedescendant","")}function Ce(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(te(t.substring(s,o)),`${te(t.substring(o,o+r.length))} `),s=o+r.length,o=n.indexOf(r,s);return i.push(te(t.substring(s))),i.join("")}var lt={"&":"&","<":"<",">":">","'":"'",'"':"""};function te(t){return t.replace(/[&<>"'"]/g,e=>lt[e])}function Pe(t,e){t.innerHTML=e?`${e}
`:""}var ct=["button","checkbox","file","hidden","image","radio","range","reset","submit"];function ut(){let t=document.activeElement;return t?t.isContentEditable||t.tagName==="TEXTAREA"||t.tagName==="SEARCH"?!0:t.tagName==="INPUT"&&!ct.includes(t.type):!1}var D="mousedown",Me="mousemove",$="mouseup",ne={x:0,y:0},Qe=!1,ce=!1,dt=!1,F=!1,Oe=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(Oe?"is-mobile":"not-mobile");Oe&&"ontouchstart"in document.documentElement&&(dt=!0,D="touchstart",Me="touchmove",$="touchend");document.addEventListener(D,t=>{ce=!0,F=!1;let e=D=="touchstart"?t.targetTouches[0]:t;ne.y=e.pageY||0,ne.x=e.pageX||0});document.addEventListener(Me,t=>{if(ce&&!F){let e=D=="touchstart"?t.targetTouches[0]:t,n=ne.x-(e.pageX||0),r=ne.y-(e.pageY||0);F=Math.sqrt(n*n+r*r)>10}});document.addEventListener($,()=>{ce=!1});document.addEventListener("click",t=>{Qe&&(t.preventDefault(),t.stopImmediatePropagation(),Qe=!1)});var re=class extends I{active;className;constructor(e){super(e),this.className=this.el.dataset.toggle||"",this.el.addEventListener($,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(D,n=>this.onDocumentPointerDown(n)),document.addEventListener($,n=>this.onDocumentPointerUp(n))}setActive(e){if(this.active==e)return;this.active=e,document.documentElement.classList.toggle("has-"+this.className,e),this.el.classList.toggle("active",e);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(e){F||(this.setActive(!0),e.preventDefault())}onDocumentPointerDown(e){if(this.active){if(e.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(e){if(!F&&this.active&&e.target.closest(".col-sidebar")){let n=e.target.closest("a");if(n){let r=window.location.href;r.indexOf("#")!=-1&&(r=r.substring(0,r.indexOf("#"))),n.href.substring(0,r.length)==r&&setTimeout(()=>this.setActive(!1),250)}}}};var ue=new Map,de=class{open;accordions=[];key;constructor(e,n){this.key=e,this.open=n}add(e){this.accordions.push(e),e.open=this.open,e.addEventListener("toggle",()=>{this.toggle(e.open)})}toggle(e){for(let n of this.accordions)n.open=e;S.setItem(this.key,e.toString())}},ie=class extends I{constructor(e){super(e);let n=this.el.querySelector("summary"),r=n.querySelector("a");r&&r.addEventListener("click",()=>{location.assign(r.href)});let i=`tsd-accordion-${n.dataset.key??n.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`,s;if(ue.has(i))s=ue.get(i);else{let o=S.getItem(i),a=o?o==="true":this.el.open;s=new de(i,a),ue.set(i,s)}s.add(this.el)}};function He(t){let e=S.getItem("tsd-theme")||"os";t.value=e,Ae(e),t.addEventListener("change",()=>{S.setItem("tsd-theme",t.value),Ae(t.value)})}function Ae(t){document.documentElement.dataset.theme=t}var se;function Ne(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",Re),Re())}async function Re(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let e=await R(window.navigationData);se=document.documentElement.dataset.base,se.endsWith("/")||(se+="/"),t.innerHTML="";for(let n of e)Be(n,t,[]);window.app.createComponents(t),window.app.showPage(),window.app.ensureActivePageVisible()}function Be(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-accordion`:"tsd-accordion";let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.dataset.key=i.join("$"),o.innerHTML=' ',De(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let c=a.appendChild(document.createElement("ul"));c.className="tsd-nested-navigation";for(let l of t.children)Be(l,c,i)}else De(t,r,t.class)}function De(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));if(r.href=se+t.path,n&&(r.className=n),location.pathname===r.pathname&&!r.href.includes("#")&&(r.classList.add("current"),r.ariaCurrent="page"),t.kind){let i=window.translations[`kind_${t.kind}`].replaceAll('"',""");r.innerHTML=` `}r.appendChild(Fe(t.text,document.createElement("span")))}else{let r=e.appendChild(document.createElement("span")),i=window.translations.folder.replaceAll('"',""");r.innerHTML=` `,r.appendChild(Fe(t.text,document.createElement("span")))}}function Fe(t,e){let n=t.split(/(?<=[^A-Z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[_-])(?=[^_-])/);for(let r=0;r{let i=r.target;for(;i.parentElement&&i.parentElement.tagName!="LI";)i=i.parentElement;i.dataset.dropdown&&(i.dataset.dropdown=String(i.dataset.dropdown!=="true"))});let t=new Map,e=new Set;for(let r of document.querySelectorAll(".tsd-full-hierarchy [data-refl]")){let i=r.querySelector("ul");t.has(r.dataset.refl)?e.add(r.dataset.refl):i&&t.set(r.dataset.refl,i)}for(let r of e)n(r);function n(r){let i=t.get(r).cloneNode(!0);i.querySelectorAll("[id]").forEach(s=>{s.removeAttribute("id")}),i.querySelectorAll("[data-dropdown]").forEach(s=>{s.dataset.dropdown="false"});for(let s of document.querySelectorAll(`[data-refl="${r}"]`)){let o=gt(),a=s.querySelector("ul");s.insertBefore(o,a),o.dataset.dropdown=String(!!a),a||s.appendChild(i.cloneNode(!0))}}}function pt(){let t=document.getElementById("tsd-hierarchy-script");t&&(t.addEventListener("load",Ve),Ve())}async function Ve(){let t=document.querySelector(".tsd-panel.tsd-hierarchy:has(h4 a)");if(!t||!window.hierarchyData)return;let e=+t.dataset.refl,n=await R(window.hierarchyData),r=t.querySelector("ul"),i=document.createElement("ul");if(i.classList.add("tsd-hierarchy"),ft(i,n,e),r.querySelectorAll("li").length==i.querySelectorAll("li").length)return;let s=document.createElement("span");s.classList.add("tsd-hierarchy-toggle"),s.textContent=window.translations.hierarchy_expand,t.querySelector("h4 a")?.insertAdjacentElement("afterend",s),s.insertAdjacentText("beforebegin",", "),s.addEventListener("click",()=>{s.textContent===window.translations.hierarchy_expand?(r.insertAdjacentElement("afterend",i),r.remove(),s.textContent=window.translations.hierarchy_collapse):(i.insertAdjacentElement("afterend",r),i.remove(),s.textContent=window.translations.hierarchy_expand)})}function ft(t,e,n){let r=e.roots.filter(i=>mt(e,i,n));for(let i of r)t.appendChild(je(e,i,n))}function je(t,e,n,r=new Set){if(r.has(e))return;r.add(e);let i=t.reflections[e],s=document.createElement("li");if(s.classList.add("tsd-hierarchy-item"),e===n){let o=s.appendChild(document.createElement("span"));o.textContent=i.name,o.classList.add("tsd-hierarchy-target")}else{for(let a of i.uniqueNameParents||[]){let c=t.reflections[a],l=s.appendChild(document.createElement("a"));l.textContent=c.name,l.href=oe+c.url,l.className=c.class+" tsd-signature-type",s.append(document.createTextNode("."))}let o=s.appendChild(document.createElement("a"));o.textContent=t.reflections[e].name,o.href=oe+i.url,o.className=i.class+" tsd-signature-type"}if(i.children){let o=s.appendChild(document.createElement("ul"));o.classList.add("tsd-hierarchy");for(let a of i.children){let c=je(t,a,n,r);c&&o.appendChild(c)}}return r.delete(e),s}function mt(t,e,n){if(e===n)return!0;let r=new Set,i=[t.reflections[e]];for(;i.length;){let s=i.pop();if(!r.has(s)){r.add(s);for(let o of s.children||[]){if(o===n)return!0;i.push(t.reflections[o])}}}return!1}function gt(){let t=document.createElementNS("http://www.w3.org/2000/svg","svg");return t.setAttribute("width","20"),t.setAttribute("height","20"),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","none"),t.innerHTML=' ',t}X(re,"a[data-toggle]");X(ie,".tsd-accordion");X(ee,".tsd-filter-item input[type=checkbox]");var qe=document.getElementById("tsd-theme");qe&&He(qe);var yt=new Z;Object.defineProperty(window,"app",{value:yt});_e();Ne();$e();"virtualKeyboard"in navigator&&(navigator.virtualKeyboard.overlaysContent=!0);})();
+/*! Bundled license information:
+
+lunr/lunr.js:
+ (**
+ * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9
+ * Copyright (C) 2020 Oliver Nightingale
+ * @license MIT
+ *)
+ (*!
+ * lunr.utils
+ * Copyright (C) 2020 Oliver Nightingale
+ *)
+ (*!
+ * lunr.Set
+ * Copyright (C) 2020 Oliver Nightingale
+ *)
+ (*!
+ * lunr.tokenizer
+ * Copyright (C) 2020 Oliver Nightingale
+ *)
+ (*!
+ * lunr.Pipeline
+ * Copyright (C) 2020 Oliver Nightingale
+ *)
+ (*!
+ * lunr.Vector
+ * Copyright (C) 2020 Oliver Nightingale
+ *)
+ (*!
+ * lunr.stemmer
+ * Copyright (C) 2020 Oliver Nightingale
+ * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt
+ *)
+ (*!
+ * lunr.stopWordFilter
+ * Copyright (C) 2020 Oliver Nightingale
+ *)
+ (*!
+ * lunr.trimmer
+ * Copyright (C) 2020 Oliver Nightingale
+ *)
+ (*!
+ * lunr.TokenSet
+ * Copyright (C) 2020 Oliver Nightingale
+ *)
+ (*!
+ * lunr.Index
+ * Copyright (C) 2020 Oliver Nightingale
+ *)
+ (*!
+ * lunr.Builder
+ * Copyright (C) 2020 Oliver Nightingale
+ *)
+*/
diff --git a/docs/assets/navigation.js b/docs/assets/navigation.js
new file mode 100644
index 0000000..d6bb656
--- /dev/null
+++ b/docs/assets/navigation.js
@@ -0,0 +1 @@
+window.navigationData = "eJyN1dtOAjEQBuB36TURz0buPISoUSESr4wX4+64VLrt2o4HYnx34wJLl3anXP9/P7bLDDz9CMJvEgNxAdkURxVJo53oiQpoKgZCakL7Chm6vl/YmVKpRE/MpM7FYP/o+LfXQFcIOdq4sczY40SVGxpbXgLBGCyUcSmoJdEHfP9AR93csrAtNHp5wyzNLWpbo8w3EOltwbrKaIccuGhsTd1iAdk8DS56SXYyuR1LraUukncPqhxez+vYKOk/K82r1Sgvog1h9/Rk72jfU+pHyLAi44/0J1gJLwpd38/b1oHPaKQvY2fXCS1SY1DIc6+59l4/dFa/nn670aaOD9vUffDZHWJYZOAMdIbqTKnl3LoYGpSSYLDLm1h0l9uQQrD1JESVJk0Sxswkxu/l5RxjEQi5K/kFBsql+5+j9ZrEsKDEgKjT3maH4Qqkc6nBzmNOE/LAhZKoo2+pCXlgKFX0G19G6cMaShxaUz5axTheiyevSyi6HqjO+OM3k9F9x+n/iD98BxoKjC76OuWJCdmOwWhCBqjAOuy6QhMygMXSfGK9qHn4X7e2Yj2W7VxGm1xDh9T5u7LKguPPf6nPT3M="
\ No newline at end of file
diff --git a/docs/assets/search.js b/docs/assets/search.js
new file mode 100644
index 0000000..abc551e
--- /dev/null
+++ b/docs/assets/search.js
@@ -0,0 +1 @@
+window.searchData = "eJytnNty2zgSht+FvlU5xtn2XSazqc1WJklNZvdG5dpiJFjmhCK1JO1Zr8vvvgUexG6hKTct39km+u8G8KEBgoCfkqr8q06ul0/Jz6xYJ9fS2EVSpFufXCcf0tWd/7prsrKok0VyX+XJdZIVja9u05Wv38Hn53fNNk8WySpP69rXyXWSPC8GUXEh9V51ndU/P5erNJixVM+CRT5aABeLZJdWvmgOgz3i+nv2P893W3elX+/ytqxWvi3Ic9qWX/XlX+9267dl9civa1f+NbWFwPzdp2tfkaz0j45igqSaZld/LKvtr2mTfkurdEuqRqX4HK7KovFF88fjjmyjCemz3qzpzOimIoKfIjJt0jne+/Knur3Ncv8l/DjDdbApOptT3e/CQ9/4am4Me8PXBxJB9rv/z72vm8kw+ud8sIq0yR78HNmzzqTamxyp16ALanShL0eq02Llc57XfdnXu6vuyRwe++oKznM00VNff/zpVy82bFdqXr4ZTKenPKIYH4w0z8u/PqfVxv/u611Z1NPsEy7OWvM8mFej+cst+sJM8aNcP84Kozc42XE7yX0r82w1z39rtxvsTg+jy+fzQtjbvIH78mfm678V6Y/cr2dG0Zr6venJwdwdmb+nohhtTna/9c1dOa8N9iYnOy+Lb1W5qXw9r/plsRvNTg6ind/mBbA3Od15X5GvxW9pVvxxV/l0XmcMAmWxTbOiGQRODmxId68ObBB468CadDMrjq786W6zrS/v56Ws0eZk98HpHNdd+de4JSboF+fNrsDs1wCeIjfz91Eed/nZF5vmbp7jfLA5wf3a16sq2029fxPOscUJrm/TLL+vmN13NpY+weXLcxp0yZzNjrusfFqz23Zf+CSHc4bFGXf5eNxp3aTNff2hXHPddgarzuAEx8fzD/TIyDyRq8mc89lv0qNLVVhsdv5hJgOg/pqU0Ndh4mWuKd9XVfr4y/3tra9mhdKUabD8MVi+bSjv68di9fp40t78DYL6mOUv044Due1M3sD5p226mes9623ewP0/vn/9MtP7n+zMxnH+GgxCBG/Y/9+bKiuOrfmoGOrB6M0CeE1LdFGc1BaHmfH798/fsqLIis1LOyZRyZmbJp+KhzTP1h981WS32Spt/Fxf3e5J1umssM6RxoirOJXGR8m5kWHTNwmm3G7L4ujm6lQsreXLu6vsUO7KI3ugE0H0Nm/hvu3u0M2/luHV7zVNspdYtxKntY28uHLCSPyJ7WATLHxa6L/RdE+ODhY1irUVWvldU4L17kNaZWGDqH4HH3MlC9/8VVY/Px1XJkoddWDB8F6vgdle+/a+WLVt9w4XmCH7JQqKVo/LcZ10++fv87x/ga0JB1GZeeKHXxEOhTkfJ6Bo7tMKf40EivuH8+S6bchJwe4xW7LyaRN9PAGa8DlXdJ3VAdRxYBLCURmueLf/elT7sAhXeuObX7IirR4Jzf2zGWIf8gxudSCx7tkMMbQWRlLhyUyh8NvHqtz+E7zbRZqg0Ax5vGxGou2jGVJoCYyUwpMZQr+lRbrxVEIaH86QO1iWIrXuGVdsl1a1n6jm/hlXrPLb8qE7/LCOdu5GXaoY38VUoqjmpYjaN1N5cXhESd0skqxY+/8m10/Jg6/qsEN2nchzdX6VLJLbzOfrcLomGVYN5XbbjcB1ubpvf7zpi/3Lr9rZ9XrZlX53kSyWFwt9cX4h1M3NYjkYtw/aPwwa419aQ5EsloIyFJGhQIYyWSwlZSgjQ4kMVbJYKspQRYYKGepksdSUoY4MNTI0yWJpFkqcG43sTGRnkJ1NFktLObSRoUWGLlksHWXoIkOHDC+TxfKSMryMDC+R4VWyWF5RhleR4RXu/4CDINERMTviAJ6WHhofgh8MkAhYCBIhETMkMEQioCFIjETMkcAgiYCHIFESMUsCwyQCI8KQxjFQAhMlAieCZErEUAlMlQisCJIrEYMlMFki8CJItkQMl8B0icCMuFoofX51gceQiAETmDAZmJEXlLGMCZOYMBmYkSRhMiZMHqQoOTHwJZGjMF8yECPp/BbzJTFfMhAjSThlzJfEfMlAjCThlDFfEvMlAzGShFPGfEnMlwzESBJOGfMlMV8yECNJOGXMl8R8yUCMJOGUMV8S86Vavkg4VcyXwnypQIwi05+K+VKYLyUnyVYxYepgGmznQUEaEzMhJkwFZhSJp4oJU5gwFZhR9BQcE6YwYcpOjCkV86UwXyoQo0iyVcyXwnypQIwiyVYxXwrzpQIxiiRbxXwpzJee5kvHfGnMl275IoeFjvnSmC8tJxHRMV8a86VbvsgxpWO+9MFSq+WLXFBoYrWF+dKBGE2OKR3zpTFfOjCjyYSvY8I0JkwHZjQ5LHRMmMaE6cCMJoeFjgnTmDAdmNH06jQmTGPCTGBGk2ybmDCDCTOBGU2ybWLCDCbMBGY0iaeJCTOYMBOY0SRhJibMYMJMu5onCTMxYeZgQd+u6EnCDLGox4SZNoORhJmYMIMJM25yJWRiwgwmzARmDImniQkzmDATmDEkniYmzGDCbGDGkHjamDCLCbOBGUPiaWPCLCbMtmsw+i0qJsxiwmxgxpB42pgwiwmzgRlD4mljwiwmzLaEkXjamDB78N7YvjiSeFri1RETZgMzlsTTxoRZTJgNzFiSMBsTZjFhNjBjScJsTJjFhLnAjCUJczFhDhPmAjOWJMzFhDlMmAvMWJIwFxPmMGEuMGPpd/WYMIcJc4EZSxLmYsIcJswFZixJmIsJc5gwF5hxJGEuJswd7E602xMkYY7YoMCEucCMIwlzMWEOE+YCM44kzMWEOUzYZWDGkYRdxoT1f2q33B581fj1p27rbbkM33sy+KHnKfl3vy9n9nt8T4m9SK6fnp/Hfbjrp2ewFReeBY/pet1/0ZrSNEBT8DQnPz+PstqNskbyZQ/uBIyCAggKxxLsTvcDiUsgccmSaA/ol8OJgFHqYlTi9QM66Q9CugIhXXW2hle74cYLEFNATM0QSfO82n/2A2hYgAavDzu9/U420ALdZ5mxwbMEgCzQi4apFD7e9RcRQUhAyOoZQsNHQiAFutEanhQ4nQAqB4QMM6bhGO+oIgGe8qKzU8wOxAfxRk0lRk2lOms9S7O7ZjgqAiKYxB9cEgEVBsFJXhLrPr4SpFrQeNaytLqbjKMEAIuXZtChZNDmErQ5j4b+029d57vhEy6oGmgmy2tzfF8Z5BqQathC3Z1c0G2g11giXddPVA6oWV6z7w9lgyYHOVTxRvJ4mXSUAcP4iicC7kqDaEAwLJmNb370X9lBywAZywtn45tV/4Ed6IDlh+NNexvfdIdGgQpYcDgeO71KsLqtym17FBoIgmnK8Tja+KY/TQpkYD5it3Z3LBSogLHveEN245vt8A0dCAGEHA/EjW+G85kgy4J05njpbH9xAExwYFrqrKTs5xWmZnmwHgBhGV717sKBtNuy2oZ0u+uu0YP2Aozz5Yj8L2Bq4/EJpcr+Ri8QBI0nZlR1EIxXnwJUVsyqbbyuVqAj1Kzqdlp5f5UAKIKBpGcojmmdqLIGVTY8UXyEEKAHJgrDmyjgv5QAMYF6MmW6G55gBoRTIC/pHNyvB1QALcHLg/GrIW4pMHEY3sQB75CCagIhyWurg3+PAKoJgBW8WWi4VwoCAn0neWOyPTJ0mO4dSBaOt6Kib5aC0EC6kLzBPdy7AmMQ1E/x4uqOLrVLkDWVKBzAy/GGDQGpAyQ4HlJk1gKNpLjBUBdnQbuDDCOZTXaP18Sg0QWP8to30aLPAZlLHuDwOhpoJFAjxWvr9lYvaBOQyiWvmfeXc4EKWBNJZhz4EhaoE9DSvIRJXaACgmCdpXmdNlyEAjMByEmal07295mACkgmmjfyh3tJQAQMU83DGF0tAkpgqGpm55fxAlTDaZLb++iGD9CC61De0Dh4WZCgu1W/NaJ5SuTlCTBZgt4zjN67WSS7bOfzrPDJ9fLm+fn/PvI4BA==";
\ No newline at end of file
diff --git a/docs/assets/style.css b/docs/assets/style.css
new file mode 100644
index 0000000..5ba5a2a
--- /dev/null
+++ b/docs/assets/style.css
@@ -0,0 +1,1633 @@
+@layer typedoc {
+ :root {
+ --dim-toolbar-contents-height: 2.5rem;
+ --dim-toolbar-border-bottom-width: 1px;
+ --dim-header-height: calc(
+ var(--dim-toolbar-border-bottom-width) +
+ var(--dim-toolbar-contents-height)
+ );
+
+ /* 0rem For mobile; unit is required for calculation in `calc` */
+ --dim-container-main-margin-y: 0rem;
+
+ --dim-footer-height: 3.5rem;
+
+ --modal-animation-duration: 0.2s;
+ }
+
+ :root {
+ /* Light */
+ --light-color-background: #f2f4f8;
+ --light-color-background-secondary: #eff0f1;
+ /* Not to be confused with [:active](https://developer.mozilla.org/en-US/docs/Web/CSS/:active) */
+ --light-color-background-active: #d6d8da;
+ --light-color-background-warning: #e6e600;
+ --light-color-warning-text: #222;
+ --light-color-accent: #c5c7c9;
+ --light-color-active-menu-item: var(--light-color-background-active);
+ --light-color-text: #222;
+ --light-color-contrast-text: #000;
+ --light-color-text-aside: #5e5e5e;
+
+ --light-color-icon-background: var(--light-color-background);
+ --light-color-icon-text: var(--light-color-text);
+
+ --light-color-comment-tag-text: var(--light-color-text);
+ --light-color-comment-tag: var(--light-color-background);
+
+ --light-color-link: #1f70c2;
+ --light-color-focus-outline: #3584e4;
+
+ --light-color-ts-keyword: #056bd6;
+ --light-color-ts-project: #b111c9;
+ --light-color-ts-module: var(--light-color-ts-project);
+ --light-color-ts-namespace: var(--light-color-ts-project);
+ --light-color-ts-enum: #7e6f15;
+ --light-color-ts-enum-member: var(--light-color-ts-enum);
+ --light-color-ts-variable: #4760ec;
+ --light-color-ts-function: #572be7;
+ --light-color-ts-class: #1f70c2;
+ --light-color-ts-interface: #108024;
+ --light-color-ts-constructor: var(--light-color-ts-class);
+ --light-color-ts-property: #9f5f30;
+ --light-color-ts-method: #be3989;
+ --light-color-ts-reference: #ff4d82;
+ --light-color-ts-call-signature: var(--light-color-ts-method);
+ --light-color-ts-index-signature: var(--light-color-ts-property);
+ --light-color-ts-constructor-signature: var(
+ --light-color-ts-constructor
+ );
+ --light-color-ts-parameter: var(--light-color-ts-variable);
+ /* type literal not included as links will never be generated to it */
+ --light-color-ts-type-parameter: #a55c0e;
+ --light-color-ts-accessor: #c73c3c;
+ --light-color-ts-get-signature: var(--light-color-ts-accessor);
+ --light-color-ts-set-signature: var(--light-color-ts-accessor);
+ --light-color-ts-type-alias: #d51270;
+ /* reference not included as links will be colored with the kind that it points to */
+ --light-color-document: #000000;
+
+ --light-color-alert-note: #0969d9;
+ --light-color-alert-tip: #1a7f37;
+ --light-color-alert-important: #8250df;
+ --light-color-alert-warning: #9a6700;
+ --light-color-alert-caution: #cf222e;
+
+ --light-external-icon: url("data:image/svg+xml;utf8, ");
+ --light-color-scheme: light;
+ }
+
+ :root {
+ /* Dark */
+ --dark-color-background: #2b2e33;
+ --dark-color-background-secondary: #1e2024;
+ /* Not to be confused with [:active](https://developer.mozilla.org/en-US/docs/Web/CSS/:active) */
+ --dark-color-background-active: #5d5d6a;
+ --dark-color-background-warning: #bebe00;
+ --dark-color-warning-text: #222;
+ --dark-color-accent: #9096a2;
+ --dark-color-active-menu-item: var(--dark-color-background-active);
+ --dark-color-text: #f5f5f5;
+ --dark-color-contrast-text: #ffffff;
+ --dark-color-text-aside: #dddddd;
+
+ --dark-color-icon-background: var(--dark-color-background-secondary);
+ --dark-color-icon-text: var(--dark-color-text);
+
+ --dark-color-comment-tag-text: var(--dark-color-text);
+ --dark-color-comment-tag: var(--dark-color-background);
+
+ --dark-color-link: #00aff4;
+ --dark-color-focus-outline: #4c97f2;
+
+ --dark-color-ts-keyword: #3399ff;
+ --dark-color-ts-project: #e358ff;
+ --dark-color-ts-module: var(--dark-color-ts-project);
+ --dark-color-ts-namespace: var(--dark-color-ts-project);
+ --dark-color-ts-enum: #f4d93e;
+ --dark-color-ts-enum-member: var(--dark-color-ts-enum);
+ --dark-color-ts-variable: #798dff;
+ --dark-color-ts-function: #a280ff;
+ --dark-color-ts-class: #8ac4ff;
+ --dark-color-ts-interface: #6cff87;
+ --dark-color-ts-constructor: var(--dark-color-ts-class);
+ --dark-color-ts-property: #ff984d;
+ --dark-color-ts-method: #ff4db8;
+ --dark-color-ts-reference: #ff4d82;
+ --dark-color-ts-call-signature: var(--dark-color-ts-method);
+ --dark-color-ts-index-signature: var(--dark-color-ts-property);
+ --dark-color-ts-constructor-signature: var(--dark-color-ts-constructor);
+ --dark-color-ts-parameter: var(--dark-color-ts-variable);
+ /* type literal not included as links will never be generated to it */
+ --dark-color-ts-type-parameter: #e07d13;
+ --dark-color-ts-accessor: #ff6060;
+ --dark-color-ts-get-signature: var(--dark-color-ts-accessor);
+ --dark-color-ts-set-signature: var(--dark-color-ts-accessor);
+ --dark-color-ts-type-alias: #ff6492;
+ /* reference not included as links will be colored with the kind that it points to */
+ --dark-color-document: #ffffff;
+
+ --dark-color-alert-note: #0969d9;
+ --dark-color-alert-tip: #1a7f37;
+ --dark-color-alert-important: #8250df;
+ --dark-color-alert-warning: #9a6700;
+ --dark-color-alert-caution: #cf222e;
+
+ --dark-external-icon: url("data:image/svg+xml;utf8, ");
+ --dark-color-scheme: dark;
+ }
+
+ @media (prefers-color-scheme: light) {
+ :root {
+ --color-background: var(--light-color-background);
+ --color-background-secondary: var(
+ --light-color-background-secondary
+ );
+ --color-background-active: var(--light-color-background-active);
+ --color-background-warning: var(--light-color-background-warning);
+ --color-warning-text: var(--light-color-warning-text);
+ --color-accent: var(--light-color-accent);
+ --color-active-menu-item: var(--light-color-active-menu-item);
+ --color-text: var(--light-color-text);
+ --color-contrast-text: var(--light-color-contrast-text);
+ --color-text-aside: var(--light-color-text-aside);
+
+ --color-icon-background: var(--light-color-icon-background);
+ --color-icon-text: var(--light-color-icon-text);
+
+ --color-comment-tag-text: var(--light-color-text);
+ --color-comment-tag: var(--light-color-background);
+
+ --color-link: var(--light-color-link);
+ --color-focus-outline: var(--light-color-focus-outline);
+
+ --color-ts-keyword: var(--light-color-ts-keyword);
+ --color-ts-project: var(--light-color-ts-project);
+ --color-ts-module: var(--light-color-ts-module);
+ --color-ts-namespace: var(--light-color-ts-namespace);
+ --color-ts-enum: var(--light-color-ts-enum);
+ --color-ts-enum-member: var(--light-color-ts-enum-member);
+ --color-ts-variable: var(--light-color-ts-variable);
+ --color-ts-function: var(--light-color-ts-function);
+ --color-ts-class: var(--light-color-ts-class);
+ --color-ts-interface: var(--light-color-ts-interface);
+ --color-ts-constructor: var(--light-color-ts-constructor);
+ --color-ts-property: var(--light-color-ts-property);
+ --color-ts-method: var(--light-color-ts-method);
+ --color-ts-reference: var(--light-color-ts-reference);
+ --color-ts-call-signature: var(--light-color-ts-call-signature);
+ --color-ts-index-signature: var(--light-color-ts-index-signature);
+ --color-ts-constructor-signature: var(
+ --light-color-ts-constructor-signature
+ );
+ --color-ts-parameter: var(--light-color-ts-parameter);
+ --color-ts-type-parameter: var(--light-color-ts-type-parameter);
+ --color-ts-accessor: var(--light-color-ts-accessor);
+ --color-ts-get-signature: var(--light-color-ts-get-signature);
+ --color-ts-set-signature: var(--light-color-ts-set-signature);
+ --color-ts-type-alias: var(--light-color-ts-type-alias);
+ --color-document: var(--light-color-document);
+
+ --color-alert-note: var(--light-color-alert-note);
+ --color-alert-tip: var(--light-color-alert-tip);
+ --color-alert-important: var(--light-color-alert-important);
+ --color-alert-warning: var(--light-color-alert-warning);
+ --color-alert-caution: var(--light-color-alert-caution);
+
+ --external-icon: var(--light-external-icon);
+ --color-scheme: var(--light-color-scheme);
+ }
+ }
+
+ @media (prefers-color-scheme: dark) {
+ :root {
+ --color-background: var(--dark-color-background);
+ --color-background-secondary: var(
+ --dark-color-background-secondary
+ );
+ --color-background-active: var(--dark-color-background-active);
+ --color-background-warning: var(--dark-color-background-warning);
+ --color-warning-text: var(--dark-color-warning-text);
+ --color-accent: var(--dark-color-accent);
+ --color-active-menu-item: var(--dark-color-active-menu-item);
+ --color-text: var(--dark-color-text);
+ --color-contrast-text: var(--dark-color-contrast-text);
+ --color-text-aside: var(--dark-color-text-aside);
+
+ --color-icon-background: var(--dark-color-icon-background);
+ --color-icon-text: var(--dark-color-icon-text);
+
+ --color-comment-tag-text: var(--dark-color-text);
+ --color-comment-tag: var(--dark-color-background);
+
+ --color-link: var(--dark-color-link);
+ --color-focus-outline: var(--dark-color-focus-outline);
+
+ --color-ts-keyword: var(--dark-color-ts-keyword);
+ --color-ts-project: var(--dark-color-ts-project);
+ --color-ts-module: var(--dark-color-ts-module);
+ --color-ts-namespace: var(--dark-color-ts-namespace);
+ --color-ts-enum: var(--dark-color-ts-enum);
+ --color-ts-enum-member: var(--dark-color-ts-enum-member);
+ --color-ts-variable: var(--dark-color-ts-variable);
+ --color-ts-function: var(--dark-color-ts-function);
+ --color-ts-class: var(--dark-color-ts-class);
+ --color-ts-interface: var(--dark-color-ts-interface);
+ --color-ts-constructor: var(--dark-color-ts-constructor);
+ --color-ts-property: var(--dark-color-ts-property);
+ --color-ts-method: var(--dark-color-ts-method);
+ --color-ts-reference: var(--dark-color-ts-reference);
+ --color-ts-call-signature: var(--dark-color-ts-call-signature);
+ --color-ts-index-signature: var(--dark-color-ts-index-signature);
+ --color-ts-constructor-signature: var(
+ --dark-color-ts-constructor-signature
+ );
+ --color-ts-parameter: var(--dark-color-ts-parameter);
+ --color-ts-type-parameter: var(--dark-color-ts-type-parameter);
+ --color-ts-accessor: var(--dark-color-ts-accessor);
+ --color-ts-get-signature: var(--dark-color-ts-get-signature);
+ --color-ts-set-signature: var(--dark-color-ts-set-signature);
+ --color-ts-type-alias: var(--dark-color-ts-type-alias);
+ --color-document: var(--dark-color-document);
+
+ --color-alert-note: var(--dark-color-alert-note);
+ --color-alert-tip: var(--dark-color-alert-tip);
+ --color-alert-important: var(--dark-color-alert-important);
+ --color-alert-warning: var(--dark-color-alert-warning);
+ --color-alert-caution: var(--dark-color-alert-caution);
+
+ --external-icon: var(--dark-external-icon);
+ --color-scheme: var(--dark-color-scheme);
+ }
+ }
+
+ :root[data-theme="light"] {
+ --color-background: var(--light-color-background);
+ --color-background-secondary: var(--light-color-background-secondary);
+ --color-background-active: var(--light-color-background-active);
+ --color-background-warning: var(--light-color-background-warning);
+ --color-warning-text: var(--light-color-warning-text);
+ --color-icon-background: var(--light-color-icon-background);
+ --color-accent: var(--light-color-accent);
+ --color-active-menu-item: var(--light-color-active-menu-item);
+ --color-text: var(--light-color-text);
+ --color-contrast-text: var(--light-color-contrast-text);
+ --color-text-aside: var(--light-color-text-aside);
+ --color-icon-text: var(--light-color-icon-text);
+
+ --color-comment-tag-text: var(--light-color-text);
+ --color-comment-tag: var(--light-color-background);
+
+ --color-link: var(--light-color-link);
+ --color-focus-outline: var(--light-color-focus-outline);
+
+ --color-ts-keyword: var(--light-color-ts-keyword);
+ --color-ts-project: var(--light-color-ts-project);
+ --color-ts-module: var(--light-color-ts-module);
+ --color-ts-namespace: var(--light-color-ts-namespace);
+ --color-ts-enum: var(--light-color-ts-enum);
+ --color-ts-enum-member: var(--light-color-ts-enum-member);
+ --color-ts-variable: var(--light-color-ts-variable);
+ --color-ts-function: var(--light-color-ts-function);
+ --color-ts-class: var(--light-color-ts-class);
+ --color-ts-interface: var(--light-color-ts-interface);
+ --color-ts-constructor: var(--light-color-ts-constructor);
+ --color-ts-property: var(--light-color-ts-property);
+ --color-ts-method: var(--light-color-ts-method);
+ --color-ts-reference: var(--light-color-ts-reference);
+ --color-ts-call-signature: var(--light-color-ts-call-signature);
+ --color-ts-index-signature: var(--light-color-ts-index-signature);
+ --color-ts-constructor-signature: var(
+ --light-color-ts-constructor-signature
+ );
+ --color-ts-parameter: var(--light-color-ts-parameter);
+ --color-ts-type-parameter: var(--light-color-ts-type-parameter);
+ --color-ts-accessor: var(--light-color-ts-accessor);
+ --color-ts-get-signature: var(--light-color-ts-get-signature);
+ --color-ts-set-signature: var(--light-color-ts-set-signature);
+ --color-ts-type-alias: var(--light-color-ts-type-alias);
+ --color-document: var(--light-color-document);
+
+ --color-note: var(--light-color-note);
+ --color-tip: var(--light-color-tip);
+ --color-important: var(--light-color-important);
+ --color-warning: var(--light-color-warning);
+ --color-caution: var(--light-color-caution);
+
+ --external-icon: var(--light-external-icon);
+ --color-scheme: var(--light-color-scheme);
+ }
+
+ :root[data-theme="dark"] {
+ --color-background: var(--dark-color-background);
+ --color-background-secondary: var(--dark-color-background-secondary);
+ --color-background-active: var(--dark-color-background-active);
+ --color-background-warning: var(--dark-color-background-warning);
+ --color-warning-text: var(--dark-color-warning-text);
+ --color-icon-background: var(--dark-color-icon-background);
+ --color-accent: var(--dark-color-accent);
+ --color-active-menu-item: var(--dark-color-active-menu-item);
+ --color-text: var(--dark-color-text);
+ --color-contrast-text: var(--dark-color-contrast-text);
+ --color-text-aside: var(--dark-color-text-aside);
+ --color-icon-text: var(--dark-color-icon-text);
+
+ --color-comment-tag-text: var(--dark-color-text);
+ --color-comment-tag: var(--dark-color-background);
+
+ --color-link: var(--dark-color-link);
+ --color-focus-outline: var(--dark-color-focus-outline);
+
+ --color-ts-keyword: var(--dark-color-ts-keyword);
+ --color-ts-project: var(--dark-color-ts-project);
+ --color-ts-module: var(--dark-color-ts-module);
+ --color-ts-namespace: var(--dark-color-ts-namespace);
+ --color-ts-enum: var(--dark-color-ts-enum);
+ --color-ts-enum-member: var(--dark-color-ts-enum-member);
+ --color-ts-variable: var(--dark-color-ts-variable);
+ --color-ts-function: var(--dark-color-ts-function);
+ --color-ts-class: var(--dark-color-ts-class);
+ --color-ts-interface: var(--dark-color-ts-interface);
+ --color-ts-constructor: var(--dark-color-ts-constructor);
+ --color-ts-property: var(--dark-color-ts-property);
+ --color-ts-method: var(--dark-color-ts-method);
+ --color-ts-reference: var(--dark-color-ts-reference);
+ --color-ts-call-signature: var(--dark-color-ts-call-signature);
+ --color-ts-index-signature: var(--dark-color-ts-index-signature);
+ --color-ts-constructor-signature: var(
+ --dark-color-ts-constructor-signature
+ );
+ --color-ts-parameter: var(--dark-color-ts-parameter);
+ --color-ts-type-parameter: var(--dark-color-ts-type-parameter);
+ --color-ts-accessor: var(--dark-color-ts-accessor);
+ --color-ts-get-signature: var(--dark-color-ts-get-signature);
+ --color-ts-set-signature: var(--dark-color-ts-set-signature);
+ --color-ts-type-alias: var(--dark-color-ts-type-alias);
+ --color-document: var(--dark-color-document);
+
+ --color-note: var(--dark-color-note);
+ --color-tip: var(--dark-color-tip);
+ --color-important: var(--dark-color-important);
+ --color-warning: var(--dark-color-warning);
+ --color-caution: var(--dark-color-caution);
+
+ --external-icon: var(--dark-external-icon);
+ --color-scheme: var(--dark-color-scheme);
+ }
+
+ html {
+ color-scheme: var(--color-scheme);
+ @media (prefers-reduced-motion: no-preference) {
+ scroll-behavior: smooth;
+ }
+ }
+
+ *:focus-visible,
+ .tsd-accordion-summary:focus-visible svg {
+ outline: 2px solid var(--color-focus-outline);
+ }
+
+ .always-visible,
+ .always-visible .tsd-signatures {
+ display: inherit !important;
+ }
+
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ line-height: 1.2;
+ }
+
+ h1 {
+ font-size: 1.875rem;
+ margin: 0.67rem 0;
+ }
+
+ h2 {
+ font-size: 1.5rem;
+ margin: 0.83rem 0;
+ }
+
+ h3 {
+ font-size: 1.25rem;
+ margin: 1rem 0;
+ }
+
+ h4 {
+ font-size: 1.05rem;
+ margin: 1.33rem 0;
+ }
+
+ h5 {
+ font-size: 1rem;
+ margin: 1.5rem 0;
+ }
+
+ h6 {
+ font-size: 0.875rem;
+ margin: 2.33rem 0;
+ }
+
+ dl,
+ menu,
+ ol,
+ ul {
+ margin: 1em 0;
+ }
+
+ dd {
+ margin: 0 0 0 34px;
+ }
+
+ .container {
+ max-width: 1700px;
+ padding: 0 2rem;
+ }
+
+ /* Footer */
+ footer {
+ border-top: 1px solid var(--color-accent);
+ padding-top: 1rem;
+ padding-bottom: 1rem;
+ max-height: var(--dim-footer-height);
+ }
+ footer > p {
+ margin: 0 1em;
+ }
+
+ .container-main {
+ margin: var(--dim-container-main-margin-y) auto;
+ /* toolbar, footer, margin */
+ min-height: calc(
+ 100svh - var(--dim-header-height) - var(--dim-footer-height) -
+ 2 * var(--dim-container-main-margin-y)
+ );
+ }
+
+ @keyframes fade-in {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+ }
+ @keyframes fade-out {
+ from {
+ opacity: 1;
+ visibility: visible;
+ }
+ to {
+ opacity: 0;
+ }
+ }
+ @keyframes pop-in-from-right {
+ from {
+ transform: translate(100%, 0);
+ }
+ to {
+ transform: translate(0, 0);
+ }
+ }
+ @keyframes pop-out-to-right {
+ from {
+ transform: translate(0, 0);
+ visibility: visible;
+ }
+ to {
+ transform: translate(100%, 0);
+ }
+ }
+ body {
+ background: var(--color-background);
+ font-family:
+ -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans",
+ Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+ font-size: 16px;
+ color: var(--color-text);
+ margin: 0;
+ }
+
+ a {
+ color: var(--color-link);
+ text-decoration: none;
+ }
+ a:hover {
+ text-decoration: underline;
+ }
+ a.external[target="_blank"] {
+ background-image: var(--external-icon);
+ background-position: top 3px right;
+ background-repeat: no-repeat;
+ padding-right: 13px;
+ }
+ a.tsd-anchor-link {
+ color: var(--color-text);
+ }
+ :target {
+ scroll-margin-block: calc(var(--dim-header-height) + 0.5rem);
+ }
+
+ code,
+ pre {
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+ padding: 0.2em;
+ margin: 0;
+ font-size: 0.875rem;
+ border-radius: 0.8em;
+ }
+
+ pre {
+ position: relative;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ padding: 10px;
+ border: 1px solid var(--color-accent);
+ margin-bottom: 8px;
+ }
+ pre code {
+ padding: 0;
+ font-size: 100%;
+ }
+ pre > button {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ opacity: 0;
+ transition: opacity 0.1s;
+ box-sizing: border-box;
+ }
+ pre:hover > button,
+ pre > button.visible,
+ pre > button:focus-visible {
+ opacity: 1;
+ }
+
+ blockquote {
+ margin: 1em 0;
+ padding-left: 1em;
+ border-left: 4px solid gray;
+ }
+
+ img {
+ max-width: 100%;
+ }
+
+ * {
+ scrollbar-width: thin;
+ scrollbar-color: var(--color-accent) var(--color-icon-background);
+ }
+
+ *::-webkit-scrollbar {
+ width: 0.75rem;
+ }
+
+ *::-webkit-scrollbar-track {
+ background: var(--color-icon-background);
+ }
+
+ *::-webkit-scrollbar-thumb {
+ background-color: var(--color-accent);
+ border-radius: 999rem;
+ border: 0.25rem solid var(--color-icon-background);
+ }
+
+ dialog {
+ border: none;
+ outline: none;
+ padding: 0;
+ background-color: var(--color-background);
+ }
+ dialog::backdrop {
+ display: none;
+ }
+ #tsd-overlay {
+ background-color: rgba(0, 0, 0, 0.5);
+ position: fixed;
+ z-index: 9999;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ animation: fade-in var(--modal-animation-duration) forwards;
+ }
+ #tsd-overlay.closing {
+ animation-name: fade-out;
+ }
+
+ .tsd-typography {
+ line-height: 1.333em;
+ }
+ .tsd-typography ul {
+ list-style: square;
+ padding: 0 0 0 20px;
+ margin: 0;
+ }
+ .tsd-typography .tsd-index-panel h3,
+ .tsd-index-panel .tsd-typography h3,
+ .tsd-typography h4,
+ .tsd-typography h5,
+ .tsd-typography h6 {
+ font-size: 1em;
+ }
+ .tsd-typography h5,
+ .tsd-typography h6 {
+ font-weight: normal;
+ }
+ .tsd-typography p,
+ .tsd-typography ul,
+ .tsd-typography ol {
+ margin: 1em 0;
+ }
+ .tsd-typography table {
+ border-collapse: collapse;
+ border: none;
+ }
+ .tsd-typography td,
+ .tsd-typography th {
+ padding: 6px 13px;
+ border: 1px solid var(--color-accent);
+ }
+ .tsd-typography thead,
+ .tsd-typography tr:nth-child(even) {
+ background-color: var(--color-background-secondary);
+ }
+
+ .tsd-alert {
+ padding: 8px 16px;
+ margin-bottom: 16px;
+ border-left: 0.25em solid var(--alert-color);
+ }
+ .tsd-alert blockquote > :last-child,
+ .tsd-alert > :last-child {
+ margin-bottom: 0;
+ }
+ .tsd-alert-title {
+ color: var(--alert-color);
+ display: inline-flex;
+ align-items: center;
+ }
+ .tsd-alert-title span {
+ margin-left: 4px;
+ }
+
+ .tsd-alert-note {
+ --alert-color: var(--color-alert-note);
+ }
+ .tsd-alert-tip {
+ --alert-color: var(--color-alert-tip);
+ }
+ .tsd-alert-important {
+ --alert-color: var(--color-alert-important);
+ }
+ .tsd-alert-warning {
+ --alert-color: var(--color-alert-warning);
+ }
+ .tsd-alert-caution {
+ --alert-color: var(--color-alert-caution);
+ }
+
+ .tsd-breadcrumb {
+ margin: 0;
+ margin-top: 1rem;
+ padding: 0;
+ color: var(--color-text-aside);
+ }
+ .tsd-breadcrumb a {
+ color: var(--color-text-aside);
+ text-decoration: none;
+ }
+ .tsd-breadcrumb a:hover {
+ text-decoration: underline;
+ }
+ .tsd-breadcrumb li {
+ display: inline;
+ }
+ .tsd-breadcrumb li:after {
+ content: " / ";
+ }
+
+ .tsd-comment-tags {
+ display: flex;
+ flex-direction: column;
+ }
+ dl.tsd-comment-tag-group {
+ display: flex;
+ align-items: center;
+ overflow: hidden;
+ margin: 0.5em 0;
+ }
+ dl.tsd-comment-tag-group dt {
+ display: flex;
+ margin-right: 0.5em;
+ font-size: 0.875em;
+ font-weight: normal;
+ }
+ dl.tsd-comment-tag-group dd {
+ margin: 0;
+ }
+ code.tsd-tag {
+ padding: 0.25em 0.4em;
+ border: 0.1em solid var(--color-accent);
+ margin-right: 0.25em;
+ font-size: 70%;
+ }
+ h1 code.tsd-tag:first-of-type {
+ margin-left: 0.25em;
+ }
+
+ dl.tsd-comment-tag-group dd:before,
+ dl.tsd-comment-tag-group dd:after {
+ content: " ";
+ }
+ dl.tsd-comment-tag-group dd pre,
+ dl.tsd-comment-tag-group dd:after {
+ clear: both;
+ }
+ dl.tsd-comment-tag-group p {
+ margin: 0;
+ }
+
+ .tsd-panel.tsd-comment .lead {
+ font-size: 1.1em;
+ line-height: 1.333em;
+ margin-bottom: 2em;
+ }
+ .tsd-panel.tsd-comment .lead:last-child {
+ margin-bottom: 0;
+ }
+
+ .tsd-filter-visibility h4 {
+ font-size: 1rem;
+ padding-top: 0.75rem;
+ padding-bottom: 0.5rem;
+ margin: 0;
+ }
+ .tsd-filter-item:not(:last-child) {
+ margin-bottom: 0.5rem;
+ }
+ .tsd-filter-input {
+ display: flex;
+ width: -moz-fit-content;
+ width: fit-content;
+ align-items: center;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ cursor: pointer;
+ }
+ .tsd-filter-input input[type="checkbox"] {
+ cursor: pointer;
+ position: absolute;
+ width: 1.5em;
+ height: 1.5em;
+ opacity: 0;
+ }
+ .tsd-filter-input input[type="checkbox"]:disabled {
+ pointer-events: none;
+ }
+ .tsd-filter-input svg {
+ cursor: pointer;
+ width: 1.5em;
+ height: 1.5em;
+ margin-right: 0.5em;
+ border-radius: 0.33em;
+ /* Leaving this at full opacity breaks event listeners on Firefox.
+ Don't remove unless you know what you're doing. */
+ opacity: 0.99;
+ }
+ .tsd-filter-input input[type="checkbox"]:focus-visible + svg {
+ outline: 2px solid var(--color-focus-outline);
+ }
+ .tsd-checkbox-background {
+ fill: var(--color-accent);
+ }
+ input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark {
+ stroke: var(--color-text);
+ }
+ .tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background {
+ fill: var(--color-background);
+ stroke: var(--color-accent);
+ stroke-width: 0.25rem;
+ }
+ .tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark {
+ stroke: var(--color-accent);
+ }
+
+ .settings-label {
+ font-weight: bold;
+ text-transform: uppercase;
+ display: inline-block;
+ }
+
+ .tsd-filter-visibility .settings-label {
+ margin: 0.75rem 0 0.5rem 0;
+ }
+
+ .tsd-theme-toggle .settings-label {
+ margin: 0.75rem 0.75rem 0 0;
+ }
+
+ .tsd-hierarchy h4 label:hover span {
+ text-decoration: underline;
+ }
+
+ .tsd-hierarchy {
+ list-style: square;
+ margin: 0;
+ }
+ .tsd-hierarchy-target {
+ font-weight: bold;
+ }
+ .tsd-hierarchy-toggle {
+ color: var(--color-link);
+ cursor: pointer;
+ }
+
+ .tsd-full-hierarchy:not(:last-child) {
+ margin-bottom: 1em;
+ padding-bottom: 1em;
+ border-bottom: 1px solid var(--color-accent);
+ }
+ .tsd-full-hierarchy,
+ .tsd-full-hierarchy ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ }
+ .tsd-full-hierarchy ul {
+ padding-left: 1.5rem;
+ }
+ .tsd-full-hierarchy a {
+ padding: 0.25rem 0 !important;
+ font-size: 1rem;
+ display: inline-flex;
+ align-items: center;
+ color: var(--color-text);
+ }
+ .tsd-full-hierarchy svg[data-dropdown] {
+ cursor: pointer;
+ }
+ .tsd-full-hierarchy svg[data-dropdown="false"] {
+ transform: rotate(-90deg);
+ }
+ .tsd-full-hierarchy svg[data-dropdown="false"] ~ ul {
+ display: none;
+ }
+
+ .tsd-panel-group.tsd-index-group {
+ margin-bottom: 0;
+ }
+ .tsd-index-panel .tsd-index-list {
+ list-style: none;
+ line-height: 1.333em;
+ margin: 0;
+ padding: 0.25rem 0 0 0;
+ overflow: hidden;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ column-gap: 1rem;
+ grid-template-rows: auto;
+ }
+ @media (max-width: 1024px) {
+ .tsd-index-panel .tsd-index-list {
+ grid-template-columns: repeat(2, 1fr);
+ }
+ }
+ @media (max-width: 768px) {
+ .tsd-index-panel .tsd-index-list {
+ grid-template-columns: repeat(1, 1fr);
+ }
+ }
+ .tsd-index-panel .tsd-index-list li {
+ -webkit-page-break-inside: avoid;
+ -moz-page-break-inside: avoid;
+ -ms-page-break-inside: avoid;
+ -o-page-break-inside: avoid;
+ page-break-inside: avoid;
+ }
+
+ .tsd-flag {
+ display: inline-block;
+ padding: 0.25em 0.4em;
+ border-radius: 4px;
+ color: var(--color-comment-tag-text);
+ background-color: var(--color-comment-tag);
+ text-indent: 0;
+ font-size: 75%;
+ line-height: 1;
+ font-weight: normal;
+ }
+
+ .tsd-anchor {
+ position: relative;
+ top: -100px;
+ }
+
+ .tsd-member {
+ position: relative;
+ }
+ .tsd-member .tsd-anchor + h3 {
+ display: flex;
+ align-items: center;
+ margin-top: 0;
+ margin-bottom: 0;
+ border-bottom: none;
+ }
+
+ .tsd-navigation.settings {
+ margin: 0;
+ margin-bottom: 1rem;
+ }
+ .tsd-navigation > a,
+ .tsd-navigation .tsd-accordion-summary {
+ width: calc(100% - 0.25rem);
+ display: flex;
+ align-items: center;
+ }
+ .tsd-navigation a,
+ .tsd-navigation summary > span,
+ .tsd-page-navigation a {
+ display: flex;
+ width: calc(100% - 0.25rem);
+ align-items: center;
+ padding: 0.25rem;
+ color: var(--color-text);
+ text-decoration: none;
+ box-sizing: border-box;
+ }
+ .tsd-navigation a.current,
+ .tsd-page-navigation a.current {
+ background: var(--color-active-menu-item);
+ color: var(--color-contrast-text);
+ }
+ .tsd-navigation a:hover,
+ .tsd-page-navigation a:hover {
+ text-decoration: underline;
+ }
+ .tsd-navigation ul,
+ .tsd-page-navigation ul {
+ margin-top: 0;
+ margin-bottom: 0;
+ padding: 0;
+ list-style: none;
+ }
+ .tsd-navigation li,
+ .tsd-page-navigation li {
+ padding: 0;
+ max-width: 100%;
+ }
+ .tsd-navigation .tsd-nav-link {
+ display: none;
+ }
+ .tsd-nested-navigation {
+ margin-left: 3rem;
+ }
+ .tsd-nested-navigation > li > details {
+ margin-left: -1.5rem;
+ }
+ .tsd-small-nested-navigation {
+ margin-left: 1.5rem;
+ }
+ .tsd-small-nested-navigation > li > details {
+ margin-left: -1.5rem;
+ }
+
+ .tsd-page-navigation-section > summary {
+ padding: 0.25rem;
+ }
+ .tsd-page-navigation-section > summary > svg {
+ margin-right: 0.25rem;
+ }
+ .tsd-page-navigation-section > div {
+ margin-left: 30px;
+ }
+ .tsd-page-navigation ul {
+ padding-left: 1.75rem;
+ }
+
+ #tsd-sidebar-links a {
+ margin-top: 0;
+ margin-bottom: 0.5rem;
+ line-height: 1.25rem;
+ }
+ #tsd-sidebar-links a:last-of-type {
+ margin-bottom: 0;
+ }
+
+ a.tsd-index-link {
+ padding: 0.25rem 0 !important;
+ font-size: 1rem;
+ line-height: 1.25rem;
+ display: inline-flex;
+ align-items: center;
+ color: var(--color-text);
+ }
+ .tsd-accordion-summary {
+ list-style-type: none; /* hide marker on non-safari */
+ outline: none; /* broken on safari, so just hide it */
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+ box-sizing: border-box;
+ }
+ .tsd-accordion-summary::-webkit-details-marker {
+ display: none; /* hide marker on safari */
+ }
+ .tsd-accordion-summary,
+ .tsd-accordion-summary a {
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
+ cursor: pointer;
+ }
+ .tsd-accordion-summary a {
+ width: calc(100% - 1.5rem);
+ }
+ .tsd-accordion-summary > * {
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ }
+ /*
+ * We need to be careful to target the arrow indicating whether the accordion
+ * is open, but not any other SVGs included in the details element.
+ */
+ .tsd-accordion:not([open]) > .tsd-accordion-summary > svg:first-child {
+ transform: rotate(-90deg);
+ }
+ .tsd-index-content > :not(:first-child) {
+ margin-top: 0.75rem;
+ }
+ .tsd-index-summary {
+ margin-top: 1.5rem;
+ margin-bottom: 0.75rem;
+ display: flex;
+ align-content: center;
+ }
+
+ .tsd-no-select {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ }
+ .tsd-kind-icon {
+ margin-right: 0.5rem;
+ width: 1.25rem;
+ height: 1.25rem;
+ min-width: 1.25rem;
+ min-height: 1.25rem;
+ }
+ .tsd-signature > .tsd-kind-icon {
+ margin-right: 0.8rem;
+ }
+
+ .tsd-panel {
+ margin-bottom: 2.5rem;
+ }
+ .tsd-panel.tsd-member {
+ margin-bottom: 4rem;
+ }
+ .tsd-panel:empty {
+ display: none;
+ }
+ .tsd-panel > h1,
+ .tsd-panel > h2,
+ .tsd-panel > h3 {
+ margin: 1.5rem -1.5rem 0.75rem -1.5rem;
+ padding: 0 1.5rem 0.75rem 1.5rem;
+ }
+ .tsd-panel > h1.tsd-before-signature,
+ .tsd-panel > h2.tsd-before-signature,
+ .tsd-panel > h3.tsd-before-signature {
+ margin-bottom: 0;
+ border-bottom: none;
+ }
+
+ .tsd-panel-group {
+ margin: 2rem 0;
+ }
+ .tsd-panel-group.tsd-index-group {
+ margin: 2rem 0;
+ }
+ .tsd-panel-group.tsd-index-group details {
+ margin: 2rem 0;
+ }
+ .tsd-panel-group > .tsd-accordion-summary {
+ margin-bottom: 1rem;
+ }
+
+ #tsd-search[open] {
+ animation: fade-in var(--modal-animation-duration) ease-out forwards;
+ }
+ #tsd-search[open].closing {
+ animation-name: fade-out;
+ }
+
+ /* Avoid setting `display` on closed dialog */
+ #tsd-search[open] {
+ display: flex;
+ flex-direction: column;
+ padding: 1rem;
+ width: 32rem;
+ max-width: 90vw;
+ max-height: calc(100vh - env(keyboard-inset-height, 0px) - 25vh);
+ /* Anchor dialog to top */
+ margin-top: 10vh;
+ border-radius: 6px;
+ will-change: max-height;
+ }
+ #tsd-search-input {
+ box-sizing: border-box;
+ width: 100%;
+ padding: 0 0.625rem; /* 10px */
+ outline: 0;
+ border: 2px solid var(--color-accent);
+ background-color: transparent;
+ color: var(--color-text);
+ border-radius: 4px;
+ height: 2.5rem;
+ flex: 0 0 auto;
+ font-size: 0.875rem;
+ transition: border-color 0.2s, background-color 0.2s;
+ }
+ #tsd-search-input:focus-visible {
+ background-color: var(--color-background-active);
+ border-color: transparent;
+ color: var(--color-contrast-text);
+ }
+ #tsd-search-input::placeholder {
+ color: inherit;
+ opacity: 0.8;
+ }
+ #tsd-search-results {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ flex: 1 1 auto;
+ display: flex;
+ flex-direction: column;
+ overflow-y: auto;
+ }
+ #tsd-search-results:not(:empty) {
+ margin-top: 0.5rem;
+ }
+ #tsd-search-results > li {
+ background-color: var(--color-background);
+ line-height: 1.5;
+ box-sizing: border-box;
+ border-radius: 4px;
+ }
+ #tsd-search-results > li:nth-child(even) {
+ background-color: var(--color-background-secondary);
+ }
+ #tsd-search-results > li:is(:hover, [aria-selected="true"]) {
+ background-color: var(--color-background-active);
+ color: var(--color-contrast-text);
+ }
+ /* It's important that this takes full size of parent `li`, to capture a click on `li` */
+ #tsd-search-results > li > a {
+ display: flex;
+ align-items: center;
+ padding: 0.5rem 0.25rem;
+ box-sizing: border-box;
+ width: 100%;
+ }
+ #tsd-search-results > li > a > .text {
+ flex: 1 1 auto;
+ min-width: 0;
+ overflow-wrap: anywhere;
+ }
+ #tsd-search-results > li > a .parent {
+ color: var(--color-text-aside);
+ }
+ #tsd-search-results > li > a mark {
+ color: inherit;
+ background-color: inherit;
+ font-weight: bold;
+ }
+ #tsd-search-status {
+ flex: 1;
+ display: grid;
+ place-content: center;
+ text-align: center;
+ overflow-wrap: anywhere;
+ }
+ #tsd-search-status:not(:empty) {
+ min-height: 6rem;
+ }
+
+ .tsd-signature {
+ margin: 0 0 1rem 0;
+ padding: 1rem 0.5rem;
+ border: 1px solid var(--color-accent);
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+ font-size: 14px;
+ overflow-x: auto;
+ }
+
+ .tsd-signature-keyword {
+ color: var(--color-ts-keyword);
+ font-weight: normal;
+ }
+
+ .tsd-signature-symbol {
+ color: var(--color-text-aside);
+ font-weight: normal;
+ }
+
+ .tsd-signature-type {
+ font-style: italic;
+ font-weight: normal;
+ }
+
+ .tsd-signatures {
+ padding: 0;
+ margin: 0 0 1em 0;
+ list-style-type: none;
+ }
+ .tsd-signatures .tsd-signature {
+ margin: 0;
+ border-color: var(--color-accent);
+ border-width: 1px 0;
+ transition: background-color 0.1s;
+ }
+ .tsd-signatures .tsd-index-signature:not(:last-child) {
+ margin-bottom: 1em;
+ }
+ .tsd-signatures .tsd-index-signature .tsd-signature {
+ border-width: 1px;
+ }
+ .tsd-description .tsd-signatures .tsd-signature {
+ border-width: 1px;
+ }
+
+ ul.tsd-parameter-list,
+ ul.tsd-type-parameter-list {
+ list-style: square;
+ margin: 0;
+ padding-left: 20px;
+ }
+ ul.tsd-parameter-list > li.tsd-parameter-signature,
+ ul.tsd-type-parameter-list > li.tsd-parameter-signature {
+ list-style: none;
+ margin-left: -20px;
+ }
+ ul.tsd-parameter-list h5,
+ ul.tsd-type-parameter-list h5 {
+ font-size: 16px;
+ margin: 1em 0 0.5em 0;
+ }
+ .tsd-sources {
+ margin-top: 1rem;
+ font-size: 0.875em;
+ }
+ .tsd-sources a {
+ color: var(--color-text-aside);
+ text-decoration: underline;
+ }
+ .tsd-sources ul {
+ list-style: none;
+ padding: 0;
+ }
+
+ .tsd-page-toolbar {
+ position: sticky;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ width: 100%;
+ color: var(--color-text);
+ background: var(--color-background-secondary);
+ border-bottom: var(--dim-toolbar-border-bottom-width)
+ var(--color-accent) solid;
+ transition: transform 0.3s ease-in-out;
+ }
+ .tsd-page-toolbar a {
+ color: var(--color-text);
+ }
+ .tsd-toolbar-contents {
+ display: flex;
+ align-items: center;
+ height: var(--dim-toolbar-contents-height);
+ margin: 0 auto;
+ }
+ .tsd-toolbar-contents > .title {
+ font-weight: bold;
+ margin-right: auto;
+ }
+ #tsd-toolbar-links {
+ display: flex;
+ align-items: center;
+ gap: 1.5rem;
+ margin-right: 1rem;
+ }
+
+ .tsd-widget {
+ box-sizing: border-box;
+ display: inline-block;
+ opacity: 0.8;
+ height: 2.5rem;
+ width: 2.5rem;
+ transition: opacity 0.1s, background-color 0.1s;
+ text-align: center;
+ cursor: pointer;
+ border: none;
+ background-color: transparent;
+ }
+ .tsd-widget:hover {
+ opacity: 0.9;
+ }
+ .tsd-widget:active {
+ opacity: 1;
+ background-color: var(--color-accent);
+ }
+ #tsd-toolbar-menu-trigger {
+ display: none;
+ }
+
+ .tsd-member-summary-name {
+ display: inline-flex;
+ align-items: center;
+ padding: 0.25rem;
+ text-decoration: none;
+ }
+
+ .tsd-anchor-icon {
+ display: inline-flex;
+ align-items: center;
+ margin-left: 0.5rem;
+ color: var(--color-text);
+ vertical-align: middle;
+ }
+
+ .tsd-anchor-icon svg {
+ width: 1em;
+ height: 1em;
+ visibility: hidden;
+ }
+
+ .tsd-member-summary-name:hover > .tsd-anchor-icon svg,
+ .tsd-anchor-link:hover > .tsd-anchor-icon svg,
+ .tsd-anchor-icon:focus-visible svg {
+ visibility: visible;
+ }
+
+ .deprecated {
+ text-decoration: line-through !important;
+ }
+
+ .warning {
+ padding: 1rem;
+ color: var(--color-warning-text);
+ background: var(--color-background-warning);
+ }
+
+ .tsd-kind-project {
+ color: var(--color-ts-project);
+ }
+ .tsd-kind-module {
+ color: var(--color-ts-module);
+ }
+ .tsd-kind-namespace {
+ color: var(--color-ts-namespace);
+ }
+ .tsd-kind-enum {
+ color: var(--color-ts-enum);
+ }
+ .tsd-kind-enum-member {
+ color: var(--color-ts-enum-member);
+ }
+ .tsd-kind-variable {
+ color: var(--color-ts-variable);
+ }
+ .tsd-kind-function {
+ color: var(--color-ts-function);
+ }
+ .tsd-kind-class {
+ color: var(--color-ts-class);
+ }
+ .tsd-kind-interface {
+ color: var(--color-ts-interface);
+ }
+ .tsd-kind-constructor {
+ color: var(--color-ts-constructor);
+ }
+ .tsd-kind-property {
+ color: var(--color-ts-property);
+ }
+ .tsd-kind-method {
+ color: var(--color-ts-method);
+ }
+ .tsd-kind-reference {
+ color: var(--color-ts-reference);
+ }
+ .tsd-kind-call-signature {
+ color: var(--color-ts-call-signature);
+ }
+ .tsd-kind-index-signature {
+ color: var(--color-ts-index-signature);
+ }
+ .tsd-kind-constructor-signature {
+ color: var(--color-ts-constructor-signature);
+ }
+ .tsd-kind-parameter {
+ color: var(--color-ts-parameter);
+ }
+ .tsd-kind-type-parameter {
+ color: var(--color-ts-type-parameter);
+ }
+ .tsd-kind-accessor {
+ color: var(--color-ts-accessor);
+ }
+ .tsd-kind-get-signature {
+ color: var(--color-ts-get-signature);
+ }
+ .tsd-kind-set-signature {
+ color: var(--color-ts-set-signature);
+ }
+ .tsd-kind-type-alias {
+ color: var(--color-ts-type-alias);
+ }
+
+ /* if we have a kind icon, don't color the text by kind */
+ .tsd-kind-icon ~ span {
+ color: var(--color-text);
+ }
+
+ /* mobile */
+ @media (max-width: 769px) {
+ #tsd-toolbar-menu-trigger {
+ display: inline-block;
+ /* temporary fix to vertically align, for compatibility */
+ line-height: 2.5;
+ }
+ #tsd-toolbar-links {
+ display: none;
+ }
+
+ .container-main {
+ display: flex;
+ }
+ .col-content {
+ float: none;
+ max-width: 100%;
+ width: 100%;
+ }
+ .col-sidebar {
+ position: fixed !important;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ z-index: 1024;
+ top: 0 !important;
+ bottom: 0 !important;
+ left: auto !important;
+ right: 0 !important;
+ padding: 1.5rem 1.5rem 0 0;
+ width: 75vw;
+ visibility: hidden;
+ background-color: var(--color-background);
+ transform: translate(100%, 0);
+ }
+ .col-sidebar > *:last-child {
+ padding-bottom: 20px;
+ }
+ .overlay {
+ content: "";
+ display: block;
+ position: fixed;
+ z-index: 1023;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.75);
+ visibility: hidden;
+ }
+
+ .to-has-menu .overlay {
+ animation: fade-in 0.4s;
+ }
+
+ .to-has-menu .col-sidebar {
+ animation: pop-in-from-right 0.4s;
+ }
+
+ .from-has-menu .overlay {
+ animation: fade-out 0.4s;
+ }
+
+ .from-has-menu .col-sidebar {
+ animation: pop-out-to-right 0.4s;
+ }
+
+ .has-menu body {
+ overflow: hidden;
+ }
+ .has-menu .overlay {
+ visibility: visible;
+ }
+ .has-menu .col-sidebar {
+ visibility: visible;
+ transform: translate(0, 0);
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+ max-height: 100vh;
+ padding: 1rem 2rem;
+ }
+ .has-menu .tsd-navigation {
+ max-height: 100%;
+ }
+ .tsd-navigation .tsd-nav-link {
+ display: flex;
+ }
+ }
+
+ /* one sidebar */
+ @media (min-width: 770px) {
+ .container-main {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
+ grid-template-areas: "sidebar content";
+ --dim-container-main-margin-y: 2rem;
+ }
+
+ .tsd-breadcrumb {
+ margin-top: 0;
+ }
+
+ .col-sidebar {
+ grid-area: sidebar;
+ }
+ .col-content {
+ grid-area: content;
+ padding: 0 1rem;
+ }
+ }
+ @media (min-width: 770px) and (max-width: 1399px) {
+ .col-sidebar {
+ max-height: calc(
+ 100vh - var(--dim-header-height) - var(--dim-footer-height) -
+ 2 * var(--dim-container-main-margin-y)
+ );
+ overflow: auto;
+ position: sticky;
+ top: calc(
+ var(--dim-header-height) + var(--dim-container-main-margin-y)
+ );
+ }
+ .site-menu {
+ margin-top: 1rem;
+ }
+ }
+
+ /* two sidebars */
+ @media (min-width: 1200px) {
+ .container-main {
+ grid-template-columns:
+ minmax(0, 1fr) minmax(0, 2.5fr) minmax(
+ 0,
+ 20rem
+ );
+ grid-template-areas: "sidebar content toc";
+ }
+
+ .col-sidebar {
+ display: contents;
+ }
+
+ .page-menu {
+ grid-area: toc;
+ padding-left: 1rem;
+ }
+ .site-menu {
+ grid-area: sidebar;
+ }
+
+ .site-menu {
+ margin-top: 0rem;
+ }
+
+ .page-menu,
+ .site-menu {
+ max-height: calc(
+ 100vh - var(--dim-header-height) - var(--dim-footer-height) -
+ 2 * var(--dim-container-main-margin-y)
+ );
+ overflow: auto;
+ position: sticky;
+ top: calc(
+ var(--dim-header-height) + var(--dim-container-main-margin-y)
+ );
+ }
+ }
+}
diff --git a/docs/functions/addInterceptor.html b/docs/functions/addInterceptor.html
new file mode 100644
index 0000000..224d6a2
--- /dev/null
+++ b/docs/functions/addInterceptor.html
@@ -0,0 +1 @@
+addInterceptor | Nativescript plugin for https requests addInterceptor ( interceptor : any ) : void Returns void Defined in packages/https/request.common.d.ts:4
diff --git a/docs/functions/addNetworkInterceptor.html b/docs/functions/addNetworkInterceptor.html
new file mode 100644
index 0000000..966b87c
--- /dev/null
+++ b/docs/functions/addNetworkInterceptor.html
@@ -0,0 +1 @@
+addNetworkInterceptor | Nativescript plugin for https requests Function addNetworkInterceptor addNetworkInterceptor ( interceptor : any ) : any Returns any Defined in packages/https/request.d.ts:127
diff --git a/docs/functions/cancelAllRequests.html b/docs/functions/cancelAllRequests.html
new file mode 100644
index 0000000..6d81a0a
--- /dev/null
+++ b/docs/functions/cancelAllRequests.html
@@ -0,0 +1 @@
+cancelAllRequests | Nativescript plugin for https requests Function cancelAllRequests Returns any Defined in packages/https/request.d.ts:125
diff --git a/docs/functions/cancelRequest.html b/docs/functions/cancelRequest.html
new file mode 100644
index 0000000..69ae540
--- /dev/null
+++ b/docs/functions/cancelRequest.html
@@ -0,0 +1 @@
+cancelRequest | Nativescript plugin for https requests cancelRequest ( tag : string ) : any Returns any Defined in packages/https/request.d.ts:124
diff --git a/docs/functions/clearCache.html b/docs/functions/clearCache.html
new file mode 100644
index 0000000..5d79c8f
--- /dev/null
+++ b/docs/functions/clearCache.html
@@ -0,0 +1 @@
+clearCache | Nativescript plugin for https requests Returns any Defined in packages/https/request.d.ts:121
diff --git a/docs/functions/clearCookies.html b/docs/functions/clearCookies.html
new file mode 100644
index 0000000..e163899
--- /dev/null
+++ b/docs/functions/clearCookies.html
@@ -0,0 +1 @@
+clearCookies | Nativescript plugin for https requests Returns any Defined in packages/https/request.d.ts:126
diff --git a/docs/functions/createRequest.html b/docs/functions/createRequest.html
new file mode 100644
index 0000000..ee871f2
--- /dev/null
+++ b/docs/functions/createRequest.html
@@ -0,0 +1 @@
+createRequest | Nativescript plugin for https requests Defined in packages/https/request.d.ts:123
diff --git a/docs/functions/disableSSLPinning.html b/docs/functions/disableSSLPinning.html
new file mode 100644
index 0000000..5c984dc
--- /dev/null
+++ b/docs/functions/disableSSLPinning.html
@@ -0,0 +1 @@
+disableSSLPinning | Nativescript plugin for https requests Function disableSSLPinning Returns any Defined in packages/https/request.d.ts:113
diff --git a/docs/functions/enableSSLPinning.html b/docs/functions/enableSSLPinning.html
new file mode 100644
index 0000000..bf0ee2f
--- /dev/null
+++ b/docs/functions/enableSSLPinning.html
@@ -0,0 +1 @@
+enableSSLPinning | Nativescript plugin for https requests Function enableSSLPinning Returns any Defined in packages/https/request.d.ts:111
diff --git a/docs/functions/getBinary.html b/docs/functions/getBinary.html
new file mode 100644
index 0000000..461d9a0
--- /dev/null
+++ b/docs/functions/getBinary.html
@@ -0,0 +1,3 @@
+getBinary | Nativescript plugin for https requests Returns Promise < ArrayBuffer > Defined in packages/https/index.d.ts:29
diff --git a/docs/functions/getClient.html b/docs/functions/getClient.html
new file mode 100644
index 0000000..36f521d
--- /dev/null
+++ b/docs/functions/getClient.html
@@ -0,0 +1 @@
+getClient | Nativescript plugin for https requests Returns any Defined in packages/https/request.d.ts:129
diff --git a/docs/functions/getFile.html b/docs/functions/getFile.html
new file mode 100644
index 0000000..0dd011a
--- /dev/null
+++ b/docs/functions/getFile.html
@@ -0,0 +1,4 @@
+getFile | Nativescript plugin for https requests Returns Promise < any > Defined in packages/https/index.d.ts:24
diff --git a/docs/functions/getFilenameFromUrl.html b/docs/functions/getFilenameFromUrl.html
new file mode 100644
index 0000000..457f811
--- /dev/null
+++ b/docs/functions/getFilenameFromUrl.html
@@ -0,0 +1 @@
+getFilenameFromUrl | Nativescript plugin for https requests Function getFilenameFromUrl getFilenameFromUrl ( url : string ) : string Returns string Defined in packages/https/request.common.d.ts:1
diff --git a/docs/functions/getImage.html b/docs/functions/getImage.html
new file mode 100644
index 0000000..f2e71a0
--- /dev/null
+++ b/docs/functions/getImage.html
@@ -0,0 +1,3 @@
+getImage | Nativescript plugin for https requests Returns Promise < ImageSource > Defined in packages/https/index.d.ts:18
diff --git a/docs/functions/getJSON.html b/docs/functions/getJSON.html
new file mode 100644
index 0000000..bb71b89
--- /dev/null
+++ b/docs/functions/getJSON.html
@@ -0,0 +1,3 @@
+getJSON | Nativescript plugin for https requests Returns Promise < T > Defined in packages/https/index.d.ts:13
diff --git a/docs/functions/getManager.html b/docs/functions/getManager.html
new file mode 100644
index 0000000..8512538
--- /dev/null
+++ b/docs/functions/getManager.html
@@ -0,0 +1 @@
+getManager | Nativescript plugin for https requests Returns any Defined in packages/https/request.d.ts:4
diff --git a/docs/functions/getString.html b/docs/functions/getString.html
new file mode 100644
index 0000000..9565a1e
--- /dev/null
+++ b/docs/functions/getString.html
@@ -0,0 +1,3 @@
+getString | Nativescript plugin for https requests Returns Promise < string > Defined in packages/https/index.d.ts:8
diff --git a/docs/functions/parseJSON.html b/docs/functions/parseJSON.html
new file mode 100644
index 0000000..bd1bb21
--- /dev/null
+++ b/docs/functions/parseJSON.html
@@ -0,0 +1 @@
+parseJSON | Nativescript plugin for https requests parseJSON ( source : string ) : any Returns any Defined in packages/https/request.common.d.ts:2
diff --git a/docs/functions/removeCachedResponse.html b/docs/functions/removeCachedResponse.html
new file mode 100644
index 0000000..e977c71
--- /dev/null
+++ b/docs/functions/removeCachedResponse.html
@@ -0,0 +1 @@
+removeCachedResponse | Nativescript plugin for https requests Function removeCachedResponse removeCachedResponse ( url : string ) : any Returns any Defined in packages/https/request.d.ts:122
diff --git a/docs/functions/request.html b/docs/functions/request.html
new file mode 100644
index 0000000..ce92e1a
--- /dev/null
+++ b/docs/functions/request.html
@@ -0,0 +1 @@
+request | Nativescript plugin for https requests Type Parameters T = any U extends boolean = true Defined in packages/https/request.d.ts:116
diff --git a/docs/functions/setCache.html b/docs/functions/setCache.html
new file mode 100644
index 0000000..2b5a713
--- /dev/null
+++ b/docs/functions/setCache.html
@@ -0,0 +1 @@
+setCache | Nativescript plugin for https requests Returns any Defined in packages/https/request.d.ts:120
diff --git a/docs/hierarchy.html b/docs/hierarchy.html
new file mode 100644
index 0000000..9f2bf40
--- /dev/null
+++ b/docs/hierarchy.html
@@ -0,0 +1 @@
+Nativescript plugin for https requests
Nativescript plugin for https requests Hierarchy Summary
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..7fc31da
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,372 @@
+Nativescript plugin for https requests
Nativescript plugin for https requests
+
+
@nativescript-community/https
+
+
+
+
+
+ Nativescript plugin for https requests
+
+
+
+
+
+
Table of Contents * [Installation](#installation)
+ * [A drop-in replacement for the [default http module](https://docs.nativescript.org/cookbook/http).](#a-drop-in-replacement-for-the-default-http-modulehttpsdocsnativescriptorgcookbookhttp)
+* [Features](#features)
+* [FAQ](#faq)
+* [Installation](#installation-1)
+* [Examples](#examples)
+ * [Hitting an API using `GET` method](#hitting-an-api-using-get-method)
+* [Configuration](#configuration)
+ * [Installing your SSL certificate](#installing-your-ssl-certificate)
+ * [Enabling SSL pinning](#enabling-ssl-pinning)
+ * [Disabling SSL pinning](#disabling-ssl-pinning)
+ * [useLegacy](#uselegacy)
+ * [Cookie](#cookie)
+ * [Enabling Cache](#enabling-cache)
+ * [Multipart form data](#multipart-form-data)
+ * [Options](#options)
+* [Webpack / bundling](#webpack--bundling)
+* [`iOS` Troubleshooting](#ios-troubleshooting)
+* [`Android` troubleshooting](#android-troubleshooting)
+
+
+
+
+
Installation Run the following command from the root of your project:
+
ns plugin add @nativescript-community/https
+
Easily integrate the most reliable native networking libraries with the latest and greatest HTTPS security features.
+
+Android: version 4.x using okhttp 4.x changing minSDKVersion to 21! If lower needed stick to 3.x
+
+
+Plugin version 2.0.0 bumps AFNetworking on iOS to 4.0.0 which no longer relies on UIWebView. Make sure to run pod repo update to get the latest AFNetworking pod on your development machine.
+
+
+
+
Features
+Modern TLS & SSL security features
+Shared connection pooling reduces request latency
+Silently recovers from common connection problems
+Everything runs on a native background thread
+Transparent GZIP
+HTTP/2 support
+Multiform part
+Cache
+Basic Cookie support
+
+
+
+
FAQ
+What the flip is SSL pinning and all this security mumbo jumbo?
+
+
How to make your apps more secure with SSL pinning .
+
+Do I have to use SSL pinning?
+
+
No. This plugin works out of the box without any security configurations needed. Either way you'll still benefit from all the features listed above.
+
+
+
Installation tns plugin add @nativescript-community/https
+Copy
+
+
+
+
Examples Hitting an API using GET method import * as Https from '@nativescript-community/https' ; Https . request ({ url: 'https://httpbin.org/get' , method: 'GET' , timeout: 30 , // seconds (default 10) }) . then ( function ( response ) { console . log ( 'Https.request response' , response ); }) . catch ( function ( error ) { console . error ( 'Https.request error' , error ); });
+Copy
+
+
+
+
Configuration Installing your SSL certificate Create a folder called assets in your projects app folder like so <project>/app/assets. Using chrome, go to the URL where the SSL certificate resides. View the details then drag and drop the certificate image into the assets folder.
+
+
Enabling SSL pinning import { knownFolders } from 'file-system' ; import * as Https from '@nativescript-community/https' ; let dir = knownFolders . currentApp (). getFolder ( 'assets' ); let certificate = dir . getFile ( 'httpbin.org.cer' ). path ; Https . enableSSLPinning ({ host: 'httpbin.org' , certificate });
+Copy
+
+
Once you've enabled SSL pinning you CAN NOT re-enable with a different host or certificate file.
+
Disabling SSL pinning import * as Https from '@nativescript-community/https' ; Https . disableSSLPinning ();
+Copy
+
+
All requests after calling this method will no longer utilize SSL pinning until it is re-enabled once again.
+
useLegacy There is a new option called useLegacy. You can set of every request options.
+When using that option the request will behave more like {N} http module.
+
+the content returned by a request is not the resulting string but an object. It follows HTTPContent format for the most part. You can call toJSON or toFile. The only difference is that toFile returns a Promise<File> which means that it is async and run in a background thread!
+an error return a content too allowing you to read its content.
+
+
Cookie By default basic Cookie support is enabled to work like in {N} http module.
+In the future more options will be added
+
Enabling Cache import { knownFolders , path } from '@nativescript/core/file-system' ; import * as Https from '@nativescript-community/https' ; Https . setCache ({ diskLocation: path . join ( knownFolders . documents (). path , 'httpcache' ), diskSize: 10 * 1024 * 1024 , // 10 MiB }); /// later on when calling your request you can use the cachePolicy option
+Copy
+
+
If you set the Content-Type header to "multipart/form-data" the request body will be evaluated as a multipart form data. Each body parameter is expected to be in this format:
+
{ data : any parameterName : string , fileName ?: string contentType ?: string }
+Copy
+
+
if fileName and contentType are set then data is expected to be either a NSData on iOS or a native.Array<number> on Android.
+
Options export interface HttpsSSLPinningOptions { host : string ; certificate : string ; allowInvalidCertificates ?: boolean ; validatesDomainName ?: boolean ; commonName ?: string ; } import { HttpRequestOptions } from 'tns-core-modules/http' ; export interface HttpsRequestOptions extends HTTPOptions { useLegacy ?: boolean ; cachePolicy ?: 'noCache' | 'onlyCache' | 'ignoreCache' ; onProgress ?: ( current : number , total : number ) => void ; }
+Copy
+
+
+
+
+SSLPinning Option
+Description
+
+
+
+
+host: string
+This must be the request domain name eg sales.company.org.
+
+
+commonName?: string
+Default: options.host, set if certificate CN is different from the host eg *.company.org (Android specific)
+
+
+certificate: string
+The uri path to your .cer certificate file.
+
+
+allowInvalidCertificates?: boolean
+Default: false. This should always be false if you are using SSL pinning. Set this to true if you're using a self-signed certificate.
+
+
+validatesDomainName?: boolean
+Default: true. Determines if the domain name should be validated with your pinned certificate.
+
+
+
+
+
+
+Requests Option
+Description
+
+
+
+
+useLegacy?: boolean
+Default: false. [IOS only] set to true in order to get the response data (when status >= 300)in the content directly instead of response.body.content.
+
+
+`cachePolicy?: 'noCache'
+'onlyCache'
+
+
+onProgress?: (current: number, total: number) => void
+[IOS only] Set the progress callback.
+
+
+
+
+
+
Webpack / bundling Since you're probably shipping a certificate with your app (like our demo does ),
+make sure it's bundled by Webpack as well. You can do this by adding the certificate(s) with the CopyWebpackPlugin .
+
+
+
iOS Troubleshooting
+Please educate yourself on iOS's App Transport Security before starting beef!
+
If you try and hit an https route without adding it to App Transport Security's whitelist it will not work!
+You can bypass this behavior by adding the following to your projects Info.plist:
+
NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+
+Copy
+
+
+This plugin does not add NSAllowsArbitraryLoads to your projects Info.plist for you.
+
+
+
+
Android troubleshootingIf you app crashes with a message that it's doing too much networking on the main thread,
+then pass the option allowLargeResponse with value true to the request function.
+
+
+
Thanks
+
Examples:
+
+
+
Demos and Development Repo Setup The repo uses submodules. If you did not clone with --recursive then you need to call
+
git submodule update -- init
+Copy
+
+
The package manager used to install and link dependencies must be pnpm or yarn. npm wont work.
+
To develop and test:
+if you use yarn then run yarn
+if you use pnpm then run pnpm i
+
Interactive Menu:
+
To start the interactive menu, run npm start (or yarn start or pnpm start). This will list all of the commonly used scripts.
+
Build npm run build.all
+Copy
+
+
WARNING: it seems yarn build.all wont always work (not finding binaries in node_modules/.bin) which is why the doc explicitly uses npm run
+
Demos npm run demo.[ng | react | svelte | vue].[ios | android] npm run demo.svelte.ios # Example
+Copy
+
+
Demo setup is a bit special in the sense that if you want to modify/add demos you dont work directly in demo-[ng|react|svelte|vue]
+Instead you work in demo-snippets/[ng|react|svelte|vue]
+You can start from the install.ts of each flavor to see how to register new demos
+
+
+
Contributing Update repo You can update the repo files quite easily
+
First update the submodules
+
npm run update
+Copy
+
+
Then commit the changes
+Then update common files
+
npm run sync
+Copy
+
+
Then you can run yarn|pnpm, commit changed files if any
+
Update readme npm run readme
+Copy
+
+
Update doc npm run doc
+Copy
+
+
Publish The publishing is completely handled by lerna (you can add -- --bump major to force a major release)
+Simply run
+
npm run publish
+Copy
+
+
modifying submodules The repo uses https:// for submodules which means you won't be able to push directly into the submodules.
+One easy solution is t modify ~/.gitconfig and add
+
[ url "ssh://git@github.com/" ] pushInsteadOf = https : //github.com/
+Copy
+
+
+
+
Questions If you have any questions/issues/comments please feel free to create an issue or start a conversation in the NativeScript Community Discord .
+
+
Demos and Development Repo Setup The repo uses submodules. If you did not clone with --recursive then you need to call
+
git submodule update -- init
+Copy
+
+
The package manager used to install and link dependencies must be pnpm or yarn. npm wont work.
+
To develop and test:
+if you use yarn then run yarn
+if you use pnpm then run pnpm i
+
Interactive Menu:
+
To start the interactive menu, run npm start (or yarn start or pnpm start). This will list all of the commonly used scripts.
+
Build npm run build.all
+Copy
+
+
WARNING: it seems yarn build.all wont always work (not finding binaries in node_modules/.bin) which is why the doc explicitly uses npm run
+
Demos npm run demo.[ng | react | svelte | vue].[ios | android] npm run demo.svelte.ios # Example
+Copy
+
+
Demo setup is a bit special in the sense that if you want to modify/add demos you dont work directly in demo-[ng|react|svelte|vue]
+Instead you work in demo-snippets/[ng|react|svelte|vue]
+You can start from the install.ts of each flavor to see how to register new demos
+
+
Contributing Update repo You can update the repo files quite easily
+
First update the submodules
+
npm run update
+Copy
+
+
Then commit the changes
+Then update common files
+
npm run sync
+Copy
+
+
Then you can run yarn|pnpm, commit changed files if any
+
Update readme npm run readme
+Copy
+
+
Update doc npm run doc
+Copy
+
+
Publish The publishing is completely handled by lerna (you can add -- --bump major to force a major release)
+Simply run
+
npm run publish
+Copy
+
+
modifying submodules The repo uses https:// for submodules which means you won't be able to push directly into the submodules.
+One easy solution is t modify ~/.gitconfig and add
+
[ url "ssh://git@github.com/" ] pushInsteadOf = https : //github.com/
+Copy
+
+
+
Questions If you have any questions/issues/comments please feel free to create an issue or start a conversation in the NativeScript Community Discord .
+
diff --git a/docs/interfaces/CacheOptions.html b/docs/interfaces/CacheOptions.html
new file mode 100644
index 0000000..a7f7af1
--- /dev/null
+++ b/docs/interfaces/CacheOptions.html
@@ -0,0 +1,5 @@
+CacheOptions | Nativescript plugin for https requests Defined in packages/https/request.d.ts:13 Properties disk Location diskLocation : string
Defined in packages/https/request.d.ts:14 disk Size diskSize : number
Defined in packages/https/request.d.ts:15 Optionalforce Cache forceCache ?: boolean
Defined in packages/https/request.d.ts:17 Optionalmemory Size memorySize ?: number
Defined in packages/https/request.d.ts:16
diff --git a/docs/interfaces/Headers.html b/docs/interfaces/Headers.html
new file mode 100644
index 0000000..5a7be43
--- /dev/null
+++ b/docs/interfaces/Headers.html
@@ -0,0 +1 @@
+Headers | Nativescript plugin for https requests Defined in packages/https/request.d.ts:31
diff --git a/docs/interfaces/HttpsFormDataParam.html b/docs/interfaces/HttpsFormDataParam.html
new file mode 100644
index 0000000..05a1cdb
--- /dev/null
+++ b/docs/interfaces/HttpsFormDataParam.html
@@ -0,0 +1,5 @@
+HttpsFormDataParam | Nativescript plugin for https requests Interface HttpsFormDataParam Defined in packages/https/request.d.ts:20 Properties Optionalcontent Type contentType ?: string
Defined in packages/https/request.d.ts:24 data data : any
Defined in packages/https/request.d.ts:21 Optionalfile Name fileName ?: string
Defined in packages/https/request.d.ts:23 parameter Name parameterName : string
Defined in packages/https/request.d.ts:22
diff --git a/docs/interfaces/HttpsRequest.html b/docs/interfaces/HttpsRequest.html
new file mode 100644
index 0000000..536cc27
--- /dev/null
+++ b/docs/interfaces/HttpsRequest.html
@@ -0,0 +1,4 @@
+HttpsRequest | Nativescript plugin for https requests Defined in packages/https/request.d.ts:90 Properties native Request nativeRequest : any
Defined in packages/https/request.d.ts:91 Methods cancel Returns any Defined in packages/https/request.d.ts:92 run run ( success : any , failure : any ) : any Returns any Defined in packages/https/request.d.ts:93
diff --git a/docs/interfaces/HttpsRequestObject.html b/docs/interfaces/HttpsRequestObject.html
new file mode 100644
index 0000000..c88769d
--- /dev/null
+++ b/docs/interfaces/HttpsRequestObject.html
@@ -0,0 +1 @@
+HttpsRequestObject | Nativescript plugin for https requests Interface HttpsRequestObject Defined in packages/https/request.d.ts:27
diff --git a/docs/interfaces/HttpsRequestOptions.html b/docs/interfaces/HttpsRequestOptions.html
new file mode 100644
index 0000000..948cbf6
--- /dev/null
+++ b/docs/interfaces/HttpsRequestOptions.html
@@ -0,0 +1,26 @@
+HttpsRequestOptions | Nativescript plugin for https requests Interface HttpsRequestOptions Defined in packages/https/request.d.ts:36 Properties Optionalallow Large Response allowLargeResponse ?: boolean
Defined in packages/https/request.d.ts:57 Optionalbody Defined in packages/https/request.d.ts:42 Optionalcache Policy Defined in packages/https/request.d.ts:70 Optionalcontent content ?: any
Optionalcookies Enabled cookiesEnabled ?: boolean
Defined in packages/https/request.d.ts:75 method method : "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS"
Optionalon Progress onProgress ?: ( current : number , total : number ) => void
Defined in packages/https/request.d.ts:62 Optionalparams Defined in packages/https/request.d.ts:41 Optionalprogress On Main Thread progressOnMainThread ?: boolean
Defined in packages/https/request.d.ts:68 Optionalresponse On Main Thread responseOnMainThread ?: boolean
Defined in packages/https/request.d.ts:67 Optionaltag tag ?: string
Defined in packages/https/request.d.ts:38 Optionaltimeout timeout ?: number
diff --git a/docs/interfaces/HttpsResponse.html b/docs/interfaces/HttpsResponse.html
new file mode 100644
index 0000000..a1a0849
--- /dev/null
+++ b/docs/interfaces/HttpsResponse.html
@@ -0,0 +1,10 @@
+HttpsResponse | Nativescript plugin for https requests Interface HttpsResponse<T> Defined in packages/https/request.d.ts:78 Properties Optionalcontent Defined in packages/https/request.d.ts:82 content Length contentLength : number
Defined in packages/https/request.d.ts:81 Optionaldescription description ?: string
Defined in packages/https/request.d.ts:85 Optionalfailure failure ?: any
Defined in packages/https/request.d.ts:87 Defined in packages/https/request.d.ts:79 Optionalreason reason ?: string
Defined in packages/https/request.d.ts:84 Optionalresponse response ?: string
Defined in packages/https/request.d.ts:83 Optionalstatus Code statusCode ?: number
Defined in packages/https/request.d.ts:80 Optionalurl url ?: string
Defined in packages/https/request.d.ts:86
diff --git a/docs/interfaces/HttpsResponseLegacy.html b/docs/interfaces/HttpsResponseLegacy.html
new file mode 100644
index 0000000..6272975
--- /dev/null
+++ b/docs/interfaces/HttpsResponseLegacy.html
@@ -0,0 +1,10 @@
+HttpsResponseLegacy | Nativescript plugin for https requests Interface HttpsResponseLegacy<T> Defined in packages/https/request.d.ts:96 Properties content Length contentLength : number
Defined in packages/https/request.d.ts:97 Methods to Array Buffer toArrayBuffer () : ArrayBuffer Returns ArrayBuffer Defined in packages/https/request.d.ts:98 to Array Buffer Async toArrayBufferAsync () : Promise < ArrayBuffer > Returns Promise < ArrayBuffer > Defined in packages/https/request.d.ts:99 to File toFile ( destinationFilePath : string ) : Promise < File > Parameters destinationFilePath : string Returns Promise < File > Defined in packages/https/request.d.ts:107 to Image toImage () : Promise < ImageSource > Returns Promise < ImageSource > Defined in packages/https/request.d.ts:105 to JSON Returns T Defined in packages/https/request.d.ts:103 to JSON Async toJSONAsync () : Promise < T > Returns Promise < T > Defined in packages/https/request.d.ts:104 to String Returns string Defined in packages/https/request.d.ts:101 to String Async toStringAsync () : Promise < string > Returns Promise < string > Defined in packages/https/request.d.ts:102
diff --git a/docs/interfaces/HttpsSSLPinningOptions.html b/docs/interfaces/HttpsSSLPinningOptions.html
new file mode 100644
index 0000000..e795190
--- /dev/null
+++ b/docs/interfaces/HttpsSSLPinningOptions.html
@@ -0,0 +1,6 @@
+HttpsSSLPinningOptions | Nativescript plugin for https requests Interface HttpsSSLPinningOptions Defined in packages/https/request.d.ts:6 Properties Optionalallow Invalid Certificates allowInvalidCertificates ?: boolean
Defined in packages/https/request.d.ts:9 certificate certificate : string
Defined in packages/https/request.d.ts:8 Optionalcommon Name commonName ?: string
Defined in packages/https/request.d.ts:11 host host : string
Defined in packages/https/request.d.ts:7 Optionalvalidates Domain Name validatesDomainName ?: boolean
Defined in packages/https/request.d.ts:10
diff --git a/docs/media/Basic.vue b/docs/media/Basic.vue
new file mode 100644
index 0000000..7f50af3
--- /dev/null
+++ b/docs/media/Basic.vue
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/modules.html b/docs/modules.html
new file mode 100644
index 0000000..7d21b63
--- /dev/null
+++ b/docs/modules.html
@@ -0,0 +1 @@
+Nativescript plugin for https requests
diff --git a/docs/types/CachePolicy.html b/docs/types/CachePolicy.html
new file mode 100644
index 0000000..5b79809
--- /dev/null
+++ b/docs/types/CachePolicy.html
@@ -0,0 +1 @@
+CachePolicy | Nativescript plugin for https requests CachePolicy : "noCache" | "onlyCache" | "ignoreCache"
Defined in packages/https/request.d.ts:35
diff --git a/docs/variables/interceptors.html b/docs/variables/interceptors.html
new file mode 100644
index 0000000..e14c4de
--- /dev/null
+++ b/docs/variables/interceptors.html
@@ -0,0 +1 @@
+interceptors | Nativescript plugin for https requests Variable interceptorsConst interceptors : any []
Defined in packages/https/request.common.d.ts:3
diff --git a/docs/variables/networkInterceptors.html b/docs/variables/networkInterceptors.html
new file mode 100644
index 0000000..472fa55
--- /dev/null
+++ b/docs/variables/networkInterceptors.html
@@ -0,0 +1 @@
+networkInterceptors | Nativescript plugin for https requests Variable networkInterceptorsConst networkInterceptors : any []
Defined in packages/https/request.common.d.ts:5
diff --git a/eslint.config.mjs b/eslint.config.mjs
new file mode 100644
index 0000000..354d869
--- /dev/null
+++ b/eslint.config.mjs
@@ -0,0 +1,3 @@
+import defaultConfig from './tools/eslint.config.mjs';
+
+export default defaultConfig;
diff --git a/lerna.json b/lerna.json
index 218c527..ae45e40 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,11 +1,28 @@
{
- "packages": [
- "plugin"
- ],
- "version": "3.3.2",
- "command": {
- "publish": {
- "conventionalCommits": true
- }
- }
+ "version": "4.1.32",
+ "$schema": "node_modules/@lerna-lite/cli/schemas/lerna-schema.json",
+ "packages": [
+ "packages/*"
+ ],
+ "npmClient": "yarn",
+ "useWorkspaces": true,
+ "command": {
+ "publish": {
+ "cleanupTempFiles": true
+ }
+ },
+ "npmClientArgs": [
+ "--no-package-lock"
+ ],
+ "commitHooks": false,
+ "createRelease": "github",
+ "conventionalCommits": true,
+ "private": false,
+ "message": "chore(release): publish new version %v",
+ "changelogPreset": "conventional-changelog-conventionalcommits",
+ "ignoreChanges": [
+ "**/__fixtures__/**",
+ "**/__tests__/**",
+ "**/*.md"
+ ]
}
diff --git a/package.json b/package.json
index 37d9807..b3b4df0 100644
--- a/package.json
+++ b/package.json
@@ -1,23 +1,38 @@
{
- "name": "@nativescript-community/https",
"version": "1.0.0",
- "description": "Nativescript plugin for gestures",
+ "description": "Nativescript plugin for https requests",
"scripts": {
- "tsc": "cp src/https.d.ts plugin && tsc -skipLibCheck -d",
- "clean": "rimraf ./plugin/**/*.d.ts ./plugin/**/*.js ./plugin/**/*.js.map plugin/node_modules plugin/package-lock.json",
+ "tsc": "cp src/index.d.ts src/request.d.ts plugin && tsc -skipLibCheck -d",
+ "clean": "rimraf -g 'packages/**/*.d.ts' 'packages/**/*.tsbuildinfo' 'packages/**/*.js' 'packages/**/*.mjs' 'packages/**/*.js.map' 'packages/**/*.mjs.map' 'packages/**/*.metada' 'packages/**/angular/ng-package.json'",
"build.plugin": " cp README.md plugin/ && rm -f .tsbuildinfo && npm run tsc",
"build.android": "bash src-native/android/build.sh",
"build.ios": "bash src-native/ios/build.sh",
"build.native": "npm run build.android && npm run build.ios",
- "build": "npm run build.plugin",
+ "build.angular": "lerna run build.angular",
+ "build": "lerna run build",
"demo.ios": "npm run build && cd ./demo && tns run ios",
"demo.android": "npm run build && cd ./demo && tns run android",
"plugin.watch.tsc": "npm run tsc -- -w",
"plugin.watch.android": "npm i && npm-watch build.android",
"plugin.watch.ios": "npm i && npm-watch build.ios",
"plugin.watch": "npm run plugin.watch.tsc & npm run plugin.watch.android & npm run plugin.watch.ios",
- "publish": "npm run build && lerna publish --create-release=github --force-publish",
- "commitmsg": "commitlint -e $GIT_PARAMS"
+ "publish": "npm run setup && npm run clean && npm run build.all && npm run readme && npm run doc && npm run commit_readme_doc_changes && lerna publish",
+ "publish.major": "npm run build && lerna publish major --create-release=github --force-publish",
+ "sync": "node ./tools/sync.mjs",
+ "commitmsg": "commitlint -e $GIT_PARAMS",
+ "build.all": "lerna run build.all",
+ "fullclean": "npm run clean && rimraf -g 'packages/**/node_modules' 'demo-*/hooks' 'demo-*/node_modules' 'package-lock.json' 'pnpm-lock.yaml' 'node_modules'",
+ "demo.vue.android": "cd ./demo-vue && ns run android --no-hmr --env.watchNodeModules",
+ "demo.vue.clean": "cd ./demo-vue && ns clean",
+ "demo.vue.ios": "cd ./demo-vue && ns run ios --no-hmr --env.watchNodeModules",
+ "doc": "node tools/builddoc.mjs",
+ "postinstall": "npm run setup",
+ "readme": "lerna run readme && node ./tools/readme.js",
+ "setup": "npm run submodules && ts-patch install",
+ "start": "./node_modules/.bin/ntl -A -s 15 -o",
+ "submodules": "git submodule update --init",
+ "update": "node ./tools/update.js",
+ "commit_readme_doc_changes": "git add docs/** *.md ; git commit -m \"readme/doc\" ; echo \"commit readme doc done\""
},
"keywords": [
"secure",
@@ -36,17 +51,25 @@
],
"contributors": [
{
- "name": "Robert Laverty",
- "email": "roblav96@gmail.com",
- "url": "https://github.com/roblav96"
+ "name": "Eddy Verbruggen",
+ "email": "eddyverbruggen@gmail.com",
+ "url": "https://github.com/EddyVerbruggen"
},
{
"name": "Kefah BADER ALDIN",
"email": "kefah.bader@gmail.com",
"url": "https://github.com/kefahB"
+ },
+ {
+ "name": "Ruslan Lekhman",
+ "email": "lekhman112@gmail.com",
+ "url": "https://github.com/lekhmanrus"
}
],
- "author": "Eddy Verbruggen (https://github.com/EddyVerbruggen)",
+ "author": {
+ "name": "Martin Guillon",
+ "email": "dev@akylas.fr"
+ },
"bugs": {
"url": "https://github.com/nativescript-community/https/issues"
},
@@ -54,46 +77,35 @@
"homepage": "https://github.com/nativescript-community/https",
"readmeFilename": "README.md",
"devDependencies": {
- "@commitlint/cli": "^9.1.2",
- "@commitlint/config-conventional": "^9.1.2",
- "@nativescript-community/observable": "^2.0.8",
- "@nativescript/core": "7.0.0",
- "@nativescript/types-android": "7.0.2",
- "@nativescript/types-ios": "7.0.1",
- "@nativescript/webpack": "3.0.2",
- "@types/node": "^13.11.1",
- "@typescript-eslint/eslint-plugin": "4.0.1",
- "@typescript-eslint/parser": "4.0.1",
- "cpy-cli": "^3.1.1",
- "eslint": "7.8.1",
- "eslint-config-prettier": "^6.13.0",
- "eslint-plugin-prettier": "^3.1.4",
- "husky": "^4.2.5",
- "lerna": "^3.22.1",
- "npm-watch": "^0.7.0",
- "prettier": "^2.1.2",
- "prompt": "^1.0.0",
- "rimraf": "^3.0.2",
- "typescript": "~3.9.7"
+ "@nativescript-community/plugin-seed-tools": "portal:tools",
+ "@nativescript-community/template-snippet": "file:demo-snippets"
},
"bootstrapper": "nativescript-plugin-seed",
- "watch": {
- "build.android": {
- "patterns": [
- "./src-native/android/gesturehandler/src"
- ],
- "extensions": "java"
- },
- "build.ios": {
- "patterns": [
- "./src-native/ios/GestureHandler"
- ],
- "extensions": "h,m"
- }
- },
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
- }
+ },
+ "ntl": {
+ "descriptions": {
+ "build": "Build the plugin",
+ "build.angular": "Build the plugin for Angular",
+ "build.all": "Build the plugin for all platforms",
+ "clean": "Clean the local environment.",
+ "demo.vue.android": "Runs the Vue demo on Android.",
+ "demo.vue.ios": "Runs the Vue demo on iOS.",
+ "watch": "Watch for changes in the plugin source and re-build."
+ }
+ },
+ "workspaces": [
+ "packages/*",
+ "demo*"
+ ],
+ "engines": {
+ "npm": "please use yarn or pnpm",
+ "yarn": ">=1.19.1",
+ "pnpm": ">=7.0.0",
+ "node": "^14.20.0 || ^16.13.0 || >=18.10.0"
+ },
+ "packageManager": "yarn@4.10.2"
}
diff --git a/packages/https/.npmignore b/packages/https/.npmignore
new file mode 100644
index 0000000..d40b4c4
--- /dev/null
+++ b/packages/https/.npmignore
@@ -0,0 +1,8 @@
+.DS_Store
+tsconfig.json
+node_modules/
+pnpm-global/
+CHANGELOG.md
+blueprint.md
+*.aar
+*.jar
\ No newline at end of file
diff --git a/packages/https/CHANGELOG.md b/packages/https/CHANGELOG.md
new file mode 100644
index 0000000..d2e2c0e
--- /dev/null
+++ b/packages/https/CHANGELOG.md
@@ -0,0 +1,379 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [4.1.32](https://github.com/nativescript-community/https/compare/v4.1.31...v4.1.32) (2026-03-31)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.31](https://github.com/nativescript-community/https/compare/v4.1.30...v4.1.31) (2026-03-30)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.30](https://github.com/nativescript-community/https/compare/v4.1.29...v4.1.30) (2026-03-28)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.29](https://github.com/nativescript-community/https/compare/v4.1.28...v4.1.29) (2026-03-27)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.28](https://github.com/nativescript-community/https/compare/v4.1.27...v4.1.28) (2026-03-26)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.27](https://github.com/nativescript-community/https/compare/v4.1.26...v4.1.27) (2026-01-14)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.26](https://github.com/nativescript-community/https/compare/v4.1.25...v4.1.26) (2025-12-18)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.25](https://github.com/nativescript-community/https/compare/v4.1.24...v4.1.25) (2025-12-11)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.24](https://github.com/nativescript-community/https/compare/v4.1.23...v4.1.24) (2025-12-11)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.23](https://github.com/nativescript-community/https/compare/v4.1.22...v4.1.23) (2025-12-11)
+
+### Bug Fixes
+
+* new option `runProgressOnMainThread` ([e53584a](https://github.com/nativescript-community/https/commit/e53584aa2f72fa917637da07987f6a763a69b59e))
+
+## [4.1.22](https://github.com/nativescript-community/https/compare/v4.1.21...v4.1.22) (2025-11-25)
+
+### Bug Fixes
+
+* **android:** improved cache control interceptor ([b92d084](https://github.com/nativescript-community/https/commit/b92d0847ea79370f5b76d0ff777c58954a29598a))
+
+## [4.1.21](https://github.com/nativescript-community/https/compare/v4.1.20...v4.1.21) (2025-10-29)
+
+### Bug Fixes
+
+* **android:** another native-api-usage fix ([f3e95a2](https://github.com/nativescript-community/https/commit/f3e95a2f3f4064a378082cf4d148bc797f2b600d))
+
+## [4.1.20](https://github.com/nativescript-community/https/compare/v4.1.19...v4.1.20) (2025-10-29)
+
+### Bug Fixes
+
+* **android:** native-api-usage fix ([43d8595](https://github.com/nativescript-community/https/commit/43d8595cf132d5705ec185a065fc9e7098d247b0))
+
+## [4.1.19](https://github.com/nativescript-community/https/compare/v4.1.18...v4.1.19) (2024-10-05)
+
+### Bug Fixes
+
+* **ios:** should fix privacy submission issue ([299bd38](https://github.com/nativescript-community/https/commit/299bd3814b648e210c38a4910e537283718ca39b))
+
+## [4.1.18](https://github.com/nativescript-community/https/compare/v4.1.17...v4.1.18) (2024-09-26)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.17](https://github.com/nativescript-community/https/compare/v4.1.16...v4.1.17) (2024-09-25)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.16](https://github.com/nativescript-community/https/compare/v4.1.15...v4.1.16) (2024-07-17)
+
+### Bug Fixes
+
+* new `responseOnMainThread` option which allows running requests from worker ([71885b3](https://github.com/nativescript-community/https/commit/71885b30f26e5e70f6cdfdb61597cd7ff87d499c))
+
+## [4.1.15](https://github.com/nativescript-community/https/compare/v4.1.14...v4.1.15) (2024-07-16)
+
+### Bug Fixes
+
+* Compiler warnings ([87a9631](https://github.com/nativescript-community/https/commit/87a9631143f5394f298047ef02308579bb8075bb))
+
+## [4.1.14](https://github.com/nativescript-community/https/compare/v4.1.13...v4.1.14) (2024-07-10)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.13](https://github.com/nativescript-community/https/compare/v4.1.12...v4.1.13) (2024-05-24)
+
+### Bug Fixes
+
+* **android:** getImage fix ([dae5f65](https://github.com/nativescript-community/https/commit/dae5f6541a8ffe4ba561021b0bd4267aaeb8a92c))
+
+## [4.1.12](https://github.com/nativescript-community/https/compare/v4.1.11...v4.1.12) (2024-04-10)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.11](https://github.com/nativescript-community/https/compare/v4.1.10...v4.1.11) (2024-04-09)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.10](https://github.com/nativescript-community/https/compare/v4.1.9...v4.1.10) (2024-03-29)
+
+### Bug Fixes
+
+* **android:** `forceCache` fix ([b3319ea](https://github.com/nativescript-community/https/commit/b3319ead68353f19e07a0eade5367ba7428e72fd))
+
+## [4.1.9](https://github.com/nativescript-community/https/compare/v4.1.8...v4.1.9) (2024-02-28)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.8](https://github.com/nativescript-community/https/compare/v4.1.7...v4.1.8) (2023-11-21)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.7](https://github.com/nativescript-community/https/compare/v4.1.6...v4.1.7) (2023-11-21)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.6](https://github.com/nativescript-community/https/compare/v4.1.4...v4.1.6) (2023-11-13)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.4](https://github.com/nativescript-community/https/compare/v4.1.3...v4.1.4) (2023-10-25)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.3](https://github.com/nativescript-community/https/compare/v4.1.2...v4.1.3) (2023-10-19)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.2](https://github.com/nativescript-community/https/compare/v4.1.1...v4.1.2) (2023-08-30)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.1.1](https://github.com/nativescript-community/https/compare/v4.1.0...v4.1.1) (2023-07-03)
+
+### Bug Fixes
+
+* angular build ([0290951](https://github.com/nativescript-community/https/commit/0290951a20d41a9158e406f6120ea9f2a1459219))
+
+# [4.1.0](https://github.com/nativescript-community/https/compare/v4.0.17...v4.1.0) (2023-04-30)
+
+### Features
+
+* angular module ([dc3761a](https://github.com/nativescript-community/https/commit/dc3761ac33d99ddaa35d47e56c3275774af647f1))
+* angular support ([ff92deb](https://github.com/nativescript-community/https/commit/ff92deb51bc95605c02eafe9ae4f066434fe8dcd))
+
+## [4.0.17](https://github.com/nativescript-community/https/compare/v4.0.16...v4.0.17) (2023-03-20)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.0.16](https://github.com/nativescript-community/https/compare/v4.0.15...v4.0.16) (2023-03-14)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.0.15](https://github.com/nativescript-community/https/compare/v4.0.14...v4.0.15) (2023-03-06)
+
+### Bug Fixes
+
+* **android:** update to latest okhttp lib ([c4b7870](https://github.com/nativescript-community/https/commit/c4b78703637e21bbfa84647d7f8a6f07348c9f44))
+
+## [4.0.14](https://github.com/nativescript-community/https/compare/v4.0.13...v4.0.14) (2023-02-15)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.0.13](https://github.com/nativescript-community/https/compare/v4.0.12...v4.0.13) (2023-01-24)
+
+### Bug Fixes
+
+* **android:** native-api-usage fix ([0f5ca06](https://github.com/nativescript-community/https/commit/0f5ca062c06c0f2c31677be8c528c1b072070e50))
+
+## [4.0.12](https://github.com/nativescript-community/https/compare/v4.0.11...v4.0.12) (2023-01-23)
+
+### Bug Fixes
+
+* **android:** improved native-api-usage ([5e32bb0](https://github.com/nativescript-community/https/commit/5e32bb08e3f95c75e0ec05d0594294911eda72af))
+
+## [4.0.11](https://github.com/nativescript-community/https/compare/v4.0.10...v4.0.11) (2022-12-05)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.0.10](https://github.com/nativescript-community/https/compare/v4.0.9...v4.0.10) (2022-11-02)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.0.9](https://github.com/nativescript-community/https/compare/v4.0.8...v4.0.9) (2022-11-02)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.0.8](https://github.com/nativescript-community/https/compare/v4.0.7...v4.0.8) (2022-09-17)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.0.7](https://github.com/nativescript-community/https/compare/v4.0.6...v4.0.7) (2022-09-17)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.0.6](https://github.com/nativescript-community/https/compare/v4.0.5...v4.0.6) (2022-05-18)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [4.0.5](https://github.com/nativescript-community/https/compare/v4.0.4...v4.0.5) (2022-04-28)
+
+### Bug Fixes
+
+* **android:** trying to fix kotlin crashes ([9c75476](https://github.com/nativescript-community/https/commit/9c7547690b72163c325e0137ad386cf51ab33db6))
+
+## [4.0.4](https://github.com/nativescript-community/https/compare/v4.0.3...v4.0.4) (2022-04-26)
+
+### Bug Fixes
+
+* **android:** should work now ([7368616](https://github.com/nativescript-community/https/commit/7368616735cdb4d3110c04a5fc19800327b5e3ed))
+
+## [4.0.3](https://github.com/nativescript-community/https/compare/v4.0.2...v4.0.3) (2022-04-26)
+
+### Bug Fixes
+
+* **android:** another fix... ([8cd3c92](https://github.com/nativescript-community/https/commit/8cd3c92980faeb6b87dfe6799b56b3b0a9375e60))
+
+## [4.0.2](https://github.com/nativescript-community/https/compare/v4.0.1...v4.0.2) (2022-04-26)
+
+### Bug Fixes
+
+* **android:** broken headers in response ([81d8479](https://github.com/nativescript-community/https/commit/81d8479a5dd44fb1e51212b8842c3409b7c23ed3))
+
+## [4.0.1](https://github.com/nativescript-community/https/compare/v4.0.0...v4.0.1) (2022-04-25)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+# [4.0.0](https://github.com/nativescript-community/https/compare/v3.4.4...v4.0.0) (2022-04-25)
+
+### Features
+
+* **android:** upgrade okhttp to 4.x. WARNING: minSDKVersion bumped to 21!
+
+## [3.4.4](https://github.com/nativescript-community/https/compare/v3.4.3...v3.4.4) (2022-04-25)
+
+### Bug Fixes
+
+* **android:** upgrade okhttp to max 3.x ([eb0b61e](https://github.com/nativescript-community/https/commit/eb0b61ea8ba53055538d5460abf0474a22ba3282))
+
+## [3.4.3](https://github.com/nativescript-community/https/compare/v3.4.2...v3.4.3) (2022-04-25)
+
+### Bug Fixes
+
+* **android:** native-api-usage fix ([bc3c7d2](https://github.com/nativescript-community/https/commit/bc3c7d24160038f48e487918ee8abcf5d24f0322))
+
+## [3.4.2](https://github.com/nativescript-community/https/compare/v3.4.1...v3.4.2) (2022-02-26)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.4.1](https://github.com/nativescript-community/https/compare/v3.4.0...v3.4.1) (2022-02-26)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+# [3.4.0](https://github.com/nativescript-community/https/compare/v3.3.13...v3.4.0) (2022-02-25)
+
+### Features
+
+* refactoring to allow N alias to replace core impl ([22ac92f](https://github.com/nativescript-community/https/commit/22ac92f572c9b2739c40f5a39f47ac67d28a78ee))
+
+## [3.3.13](https://github.com/nativescript-community/https/compare/v3.3.12...v3.3.13) (2022-02-08)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.3.12](https://github.com/nativescript-community/https/compare/v3.3.11...v3.3.12) (2022-01-20)
+
+### Bug Fixes
+
+* **android:** progress support for uploading ([67817ac](https://github.com/nativescript-community/https/commit/67817ac284f8da424829b0c400b5c2c788ccf9dc))
+
+## [3.3.11](https://github.com/nativescript-community/https/compare/v3.3.10...v3.3.11) (2022-01-20)
+
+### Bug Fixes
+
+* **android:** native-api-usage fix ([06dc376](https://github.com/nativescript-community/https/commit/06dc376b01683675ef2a90135396ec5a9f1cf60a))
+
+## [3.3.10](https://github.com/nativescript-community/https/compare/v3.3.9...v3.3.10) (2022-01-19)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.3.9](https://github.com/nativescript-community/https/compare/v3.3.8...v3.3.9) (2022-01-18)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.3.8](https://github.com/farfromrefug/nativescript-https/compare/v3.3.7...v3.3.8) (2022-01-18)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.3.7](https://github.com/farfromrefug/nativescript-https/compare/v3.3.6...v3.3.7) (2022-01-15)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.3.6](https://github.com/farfromrefug/nativescript-https/compare/v3.3.5...v3.3.6) (2022-01-15)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.3.5](https://github.com/farfromrefug/nativescript-https/compare/v3.3.4...v3.3.5) (2022-01-14)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.3.4](https://github.com/farfromrefug/nativescript-https/compare/v3.3.3...v3.3.4) (2022-01-14)
+
+### Bug Fixes
+
+* **android:** missing native-api-usage ([0d6d67b](https://github.com/farfromrefug/nativescript-https/commit/0d6d67b223e52d5e3d80b4513f2ee6d591495e4f))
+
+## [3.3.3](https://github.com/farfromrefug/nativescript-https/compare/v3.3.2...v3.3.3) (2021-12-23)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.3.2](https://github.com/farfromrefug/nativescript-https/compare/v3.3.1...v3.3.2) (2021-10-21)
+
+### Bug Fixes
+
+* **android:** native-api-usage fix ([6f8748d](https://github.com/farfromrefug/nativescript-https/commit/6f8748da0323eb2520dbb5024301deb136bd5baa))
+
+## [3.3.1](https://github.com/farfromrefug/nativescript-https/compare/v3.3.0...v3.3.1) (2021-10-18)
+
+### Bug Fixes
+
+* **android:** native-api-usage fix ([e18a203](https://github.com/farfromrefug/nativescript-https/commit/e18a2039464d488f3e370dd7feaf6ed61e4938e6))
+
+# [3.3.0](https://github.com/farfromrefug/nativescript-https/compare/v3.2.2...v3.3.0) (2021-10-17)
+
+### Bug Fixes
+
+* **android:** Conscrypt not included by default anymore. You need to add it in your app ([c16f34d](https://github.com/farfromrefug/nativescript-https/commit/c16f34d1b2f3fa226760ab00b17e56f6996dff96))
+
+### Features
+
+* **android:** native-api-usage ([9415f38](https://github.com/farfromrefug/nativescript-https/commit/9415f387b929b01c7fe385ff5d42e1bbd15ae2e4))
+
+## [3.2.2](https://github.com/farfromrefug/nativescript-https/compare/v3.2.1...v3.2.2) (2021-07-21)
+
+### Bug Fixes
+
+* **android:** prevent error when no cache-control ([e3d781e](https://github.com/farfromrefug/nativescript-https/commit/e3d781ed3a2d7364d3179d6a5acc39b5b9b65e29))
+
+## [3.2.1](https://github.com/farfromrefug/nativescript-https/compare/v3.2.0...v3.2.1) (2021-07-01)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+# [3.2.0](https://github.com/farfromrefug/nativescript-https/compare/v3.1.3...v3.2.0) (2021-03-14)
+
+### Features
+
+* **android:** forceCache option ([cc225be](https://github.com/farfromrefug/nativescript-https/commit/cc225bea37e0035288533106e48a469e11d15d01))
+
+## [3.1.3](https://github.com/farfromrefug/nativescript-https/compare/v3.1.2...v3.1.3) (2021-03-12)
+
+**Note:** Version bump only for package @nativescript-community/https
+
+## [3.1.2](https://github.com/farfromrefug/nativescript-https/compare/v3.1.1...v3.1.2) (2020-12-09)
+
+### Bug Fixes
+
+* ios crash with cache on < 13 ([e021b8d](https://github.com/farfromrefug/nativescript-https/commit/e021b8d9c847f5ba545cc6fc52e6271780dd4e7f))
+
+## [3.1.1](https://github.com/farfromrefug/nativescript-https/compare/v3.1.0...v3.1.1) (2020-11-26)
+
+### Bug Fixes
+
+* correctly handle null responses from requests ([6b70be6](https://github.com/farfromrefug/nativescript-https/commit/6b70be64eb44a7e3da1705f025128bd9fabe6d2a))
+
+# 3.1.0 (2020-10-29)
+
+### Features
+
+* move to @nativescript-community/https ([5c8d5c8](https://github.com/farfromrefug/nativescript-https/commit/5c8d5c8c4e5e7d50a0312cf978638b6068398025))
diff --git a/packages/https/README.md b/packages/https/README.md
new file mode 100644
index 0000000..6d5ca89
--- /dev/null
+++ b/packages/https/README.md
@@ -0,0 +1,406 @@
+
+
+@nativescript-community/https
+
+
+
+
+
+
+ Nativescript plugin for https requests
+
+
+
+
+
+
+
+[](#table-of-contents)
+
+## Table of Contents
+
+ * [Installation](#installation)
+ * [A drop-in replacement for the [default http module](https://docs.nativescript.org/cookbook/http).](#a-drop-in-replacement-for-the-default-http-modulehttpsdocsnativescriptorgcookbookhttp)
+ * [Features](#features)
+ * [FAQ](#faq)
+ * [Installation](#installation-1)
+ * [Examples](#examples)
+ * [Hitting an API using `GET` method](#hitting-an-api-using-get-method)
+ * [Configuration](#configuration)
+ * [Installing your SSL certificate](#installing-your-ssl-certificate)
+ * [Enabling SSL pinning](#enabling-ssl-pinning)
+ * [Disabling SSL pinning](#disabling-ssl-pinning)
+ * [useLegacy](#uselegacy)
+ * [Cookie](#cookie)
+ * [Enabling Cache](#enabling-cache)
+ * [Multipart form data](#multipart-form-data)
+ * [Options](#options)
+ * [Webpack / bundling](#webpack--bundling)
+ * [`iOS` Troubleshooting](#ios-troubleshooting)
+ * [`Android` troubleshooting](#android-troubleshooting)
+* [Thanks](#thanks)
+ * [Examples:](#examples-1)
+ * [Demos and Development](#demos-and-development)
+ * [Repo Setup](#repo-setup)
+ * [Build](#build)
+ * [Demos](#demos)
+ * [Contributing](#contributing)
+ * [Update repo ](#update-repo-)
+ * [Update readme ](#update-readme-)
+ * [Update doc ](#update-doc-)
+ * [Publish](#publish)
+ * [modifying submodules](#modifying-submodules)
+ * [Questions](#questions)
+
+
+[](#installation)
+
+## Installation
+Run the following command from the root of your project:
+
+`ns plugin add @nativescript-community/https`
+
+Easily integrate the most reliable native networking libraries with the latest and greatest HTTPS security features.
+
+> Android: version 4.x using okhttp 4.x changing minSDKVersion to 21! If lower needed stick to 3.x
+
+> Plugin version 2.0.0 bumps `AFNetworking` on iOS to [4.0.0](https://github.com/AFNetworking/AFNetworking/releases/tag/4.0.0) which no longer relies on `UIWebView`. Make sure to run `pod repo update` to get the latest `AFNetworking` pod on your development machine.
+
+#### A drop-in replacement for the [default http module](https://docs.nativescript.org/cookbook/http).
+
+
+[](#features)
+
+## Features
+
+- Modern TLS & SSL security features
+- Shared connection pooling reduces request latency
+- Silently recovers from common connection problems
+- Everything runs on a native background thread
+- Transparent GZIP
+- HTTP/2 support
+- Multiform part
+- Cache
+- Basic Cookie support
+
+
+[](#faq)
+
+## FAQ
+
+> What the flip is SSL pinning and all this security mumbo jumbo?
+
+[How to make your apps more secure with SSL pinning](https://infinum.co/the-capsized-eight/how-to-make-your-ios-apps-more-secure-with-ssl-pinning).
+
+> Do I have to use SSL pinning?
+
+**No.** This plugin works out of the box without any security configurations needed. Either way you'll still benefit from all the features listed above.
+
+
+
+[](#installation)
+
+## Installation
+
+```bash
+tns plugin add @nativescript-community/https
+```
+
+
+[](#examples)
+
+## Examples
+
+### Hitting an API using `GET` method
+
+```typescript
+import * as Https from '@nativescript-community/https';
+Https.request({
+ url: 'https://httpbin.org/get',
+ method: 'GET',
+ timeout: 30, // seconds (default 10)
+})
+ .then(function (response) {
+ console.log('Https.request response', response);
+ })
+ .catch(function (error) {
+ console.error('Https.request error', error);
+ });
+```
+
+
+[](#configuration)
+
+## Configuration
+
+### Installing your SSL certificate
+
+Create a folder called `assets` in your projects `app` folder like so `/app/assets`. Using chrome, go to the URL where the SSL certificate resides. View the details then drag and drop the certificate image into the `assets` folder.
+
+
+
+#### Enabling SSL pinning
+
+```typescript
+import { knownFolders } from 'file-system';
+import * as Https from '@nativescript-community/https';
+let dir = knownFolders.currentApp().getFolder('assets');
+let certificate = dir.getFile('httpbin.org.cer').path;
+Https.enableSSLPinning({ host: 'httpbin.org', certificate });
+```
+
+Once you've enabled SSL pinning you **CAN NOT** re-enable with a different `host` or `certificate` file.
+
+#### Disabling SSL pinning
+
+```typescript
+import * as Https from '@nativescript-community/https';
+Https.disableSSLPinning();
+```
+
+All requests after calling this method will no longer utilize SSL pinning until it is re-enabled once again.
+
+### useLegacy
+
+There is a new option called `useLegacy`. You can set of every request options.
+When using that option the request will behave more like {N} http module.
+
+- the `content` returned by a request is not the resulting string but an object. It follows [HTTPContent](https://docs.nativescript.org/api-reference/interfaces/_http_.httpcontent) format for the most part. You can call `toJSON` or `toFile`. The only difference is that `toFile` returns a `Promise` which means that it is async and run in a background thread!
+- an error return a `content` too allowing you to read its content.
+
+### Cookie
+
+By default basic Cookie support is enabled to work like in {N} `http` module.
+In the future more options will be added
+
+### Enabling Cache
+
+```typescript
+import { knownFolders, path } from '@nativescript/core/file-system';
+import * as Https from '@nativescript-community/https';
+Https.setCache({
+ diskLocation: path.join(knownFolders.documents().path, 'httpcache'),
+ diskSize: 10 * 1024 * 1024, // 10 MiB
+});
+
+/// later on when calling your request you can use the cachePolicy option
+```
+
+### Multipart form data
+
+If you set the `Content-Type` header to `"multipart/form-data"` the request body will be evaluated as a multipart form data. Each body parameter is expected to be in this format:
+
+```typescript
+{
+ data: any
+ parameterName: string,
+ fileName?: string
+ contentType?: string
+}
+
+```
+
+if `fileName` and `contentType` are set then data is expected to be either a `NSData` on iOS or a `native.Array` on Android.
+
+### Options
+
+```typescript
+export interface HttpsSSLPinningOptions {
+ host: string;
+ certificate: string;
+ allowInvalidCertificates?: boolean;
+ validatesDomainName?: boolean;
+ commonName?: string;
+}
+import { HttpRequestOptions } from 'tns-core-modules/http';
+export interface HttpsRequestOptions extends HTTPOptions {
+ useLegacy?: boolean;
+ cachePolicy?: 'noCache' | 'onlyCache' | 'ignoreCache';
+ onProgress?: (current: number, total: number) => void;
+}
+```
+
+| SSLPinning Option | Description |
+| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
+| `host: string` | This must be the request domain name eg `sales.company.org`. |
+| `commonName?: string` | Default: options.host, set if certificate CN is different from the host eg `*.company.org` (Android specific) |
+| `certificate: string` | The uri path to your `.cer` certificate file. |
+| `allowInvalidCertificates?: boolean` | Default: `false`. This should **always** be `false` if you are using SSL pinning. Set this to `true` if you're using a self-signed certificate. |
+| `validatesDomainName?: boolean` | Default: `true`. Determines if the domain name should be validated with your pinned certificate. |
+
+| Requests Option | Description |
+| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `useLegacy?: boolean` | Default: `false`. [IOS only] set to true in order to get the response data (when status >= 300)in the `content` directly instead of `response.body.content`. |
+| `cachePolicy?: 'noCache' | 'onlyCache' | 'ignoreCache'` | Set the cache policy to use with that request. This only works with GET requests for now. |
+| `onProgress?: (current: number, total: number) => void` | [IOS only] Set the progress callback. |
+
+
+[](#webpack--bundling)
+
+## Webpack / bundling
+
+Since you're probably shipping a certificate with your app (like [our demo does](https://github.com/nativescript-community/https/tree/master/demo/app/assets)),
+make sure it's bundled by Webpack as well. You can do this by [adding the certificate(s) with the `CopyWebpackPlugin`](https://github.com/nativescript-community/https/blob/a5c841c0af7ff6d9994fa23f7fba0df0514c58f1/demo/webpack.config.js#L240).
+
+
+[](#ios-troubleshooting)
+
+## `iOS` Troubleshooting
+
+> ### Please educate yourself on iOS's [App Transport Security](https://github.com/codepath/ios_guides/wiki/App-Transport-Security) before starting beef!
+
+If you try and hit an `https` route without adding it to App Transport Security's whitelist it will not work!
+You can bypass this behavior by adding the following to your projects `Info.plist`:
+
+```xml
+NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+
+```
+
+> This plugin **does not** add `NSAllowsArbitraryLoads` to your projects `Info.plist` for you.
+
+
+[](#android-troubleshooting)
+
+## `Android` troubleshooting
+
+If you app crashes with a message that it's doing too much networking on the main thread,
+then pass the option `allowLargeResponse` with value `true` to the `request` function.
+
+
+[](#thanks)
+
+# Thanks
+
+| Who | Why |
+| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [Robert Laverty](https://github.com/roblav96) | For creating and maintaining this plugin for a long time |
+| [Jeff Whelple](https://github.com/gethuman) | For contributing |
+| [Eddy Verbruggen](https://github.com/EddyVerbruggen) | For maintaining this before it got transferred |
+| [AFNetworking](https://github.com/AFNetworking) | [AFNetworking](https://github.com/AFNetworking/AFNetworking) A delightful networking framework for iOS, OS X, watchOS, and tvOS. |
+| [Square](http://square.github.io/) | [okhttp](https://github.com/square/okhttp) An HTTP+HTTP/2 client for Android and Java applications. |
+
+### Examples:
+
+- [Basic](demo-snippets/vue/Basic.vue)
+ - A basic example
+
+
+[](#demos-and-development)
+
+## Demos and Development
+
+
+### Repo Setup
+
+The repo uses submodules. If you did not clone with ` --recursive` then you need to call
+```
+git submodule update --init
+```
+
+The package manager used to install and link dependencies must be `pnpm` or `yarn`. `npm` wont work.
+
+To develop and test:
+if you use `yarn` then run `yarn`
+if you use `pnpm` then run `pnpm i`
+
+**Interactive Menu:**
+
+To start the interactive menu, run `npm start` (or `yarn start` or `pnpm start`). This will list all of the commonly used scripts.
+
+### Build
+
+```bash
+npm run build.all
+```
+WARNING: it seems `yarn build.all` wont always work (not finding binaries in `node_modules/.bin`) which is why the doc explicitly uses `npm run`
+
+### Demos
+
+```bash
+npm run demo.[ng|react|svelte|vue].[ios|android]
+
+npm run demo.svelte.ios # Example
+```
+
+Demo setup is a bit special in the sense that if you want to modify/add demos you dont work directly in `demo-[ng|react|svelte|vue]`
+Instead you work in `demo-snippets/[ng|react|svelte|vue]`
+You can start from the `install.ts` of each flavor to see how to register new demos
+
+
+[](#contributing)
+
+## Contributing
+
+### Update repo
+
+You can update the repo files quite easily
+
+First update the submodules
+
+```bash
+npm run update
+```
+
+Then commit the changes
+Then update common files
+
+```bash
+npm run sync
+```
+Then you can run `yarn|pnpm`, commit changed files if any
+
+### Update readme
+```bash
+npm run readme
+```
+
+### Update doc
+```bash
+npm run doc
+```
+
+### Publish
+
+The publishing is completely handled by `lerna` (you can add `-- --bump major` to force a major release)
+Simply run
+```shell
+npm run publish
+```
+
+### modifying submodules
+
+The repo uses https:// for submodules which means you won't be able to push directly into the submodules.
+One easy solution is t modify `~/.gitconfig` and add
+```
+[url "ssh://git@github.com/"]
+ pushInsteadOf = https://github.com/
+```
+
+
+[](#questions)
+
+## Questions
+
+If you have any questions/issues/comments please feel free to create an issue or start a conversation in the [NativeScript Community Discord](https://nativescript.org/discord).
\ No newline at end of file
diff --git a/packages/https/angular/package.json b/packages/https/angular/package.json
new file mode 100644
index 0000000..64a280a
--- /dev/null
+++ b/packages/https/angular/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "@nativescript-community/https-angular",
+ "main": "index.js",
+ "module": "fesm2022/nativescript-community-https-angular.mjs",
+ "typings": "index.d.ts",
+ "exports": {
+ "./package.json": {
+ "default": "./package.json"
+ },
+ ".": {
+ "types": "./index.d.ts",
+ "esm2022": "./esm2022/nativescript-community-https-angular.mjs",
+ "esm": "./esm2022/nativescript-community-https-angular.mjs",
+ "default": "./fesm2022/nativescript-community-https-angular.mjs"
+ }
+ },
+ "sideEffects": false,
+ "dependencies": {
+ "tslib": "^2.3.0"
+ },
+ "scripts": {
+ "prepublishOnly": "node --eval \"console.error('ERROR: Trying to publish a package that has been compiled by Ivy in full compilation mode. This is not allowed.\\nPlease delete and rebuild the package with Ivy partial compilation mode, before attempting to publish.\\n')\" && exit 1"
+ }
+}
\ No newline at end of file
diff --git a/packages/https/blueprint.md b/packages/https/blueprint.md
new file mode 100644
index 0000000..df25b27
--- /dev/null
+++ b/packages/https/blueprint.md
@@ -0,0 +1,215 @@
+{{ load:../../tools/readme/edit-warning.md }}
+{{ template:title }}
+{{ template:badges }}
+{{ template:description }}
+
+{{ template:toc }}
+
+## Installation
+Run the following command from the root of your project:
+
+`ns plugin add {{ pkg.name }}`
+
+Easily integrate the most reliable native networking libraries with the latest and greatest HTTPS security features.
+
+> Android: version 4.x using okhttp 4.x changing minSDKVersion to 21! If lower needed stick to 3.x
+
+> Plugin version 2.0.0 bumps `AFNetworking` on iOS to [4.0.0](https://github.com/AFNetworking/AFNetworking/releases/tag/4.0.0) which no longer relies on `UIWebView`. Make sure to run `pod repo update` to get the latest `AFNetworking` pod on your development machine.
+
+#### A drop-in replacement for the [default http module](https://docs.nativescript.org/cookbook/http).
+
+## Features
+
+- Modern TLS & SSL security features
+- Shared connection pooling reduces request latency
+- Silently recovers from common connection problems
+- Everything runs on a native background thread
+- Transparent GZIP
+- HTTP/2 support
+- Multiform part
+- Cache
+- Basic Cookie support
+
+## FAQ
+
+> What the flip is SSL pinning and all this security mumbo jumbo?
+
+[How to make your apps more secure with SSL pinning](https://infinum.co/the-capsized-eight/how-to-make-your-ios-apps-more-secure-with-ssl-pinning).
+
+> Do I have to use SSL pinning?
+
+**No.** This plugin works out of the box without any security configurations needed. Either way you'll still benefit from all the features listed above.
+
+
+## Installation
+
+```bash
+tns plugin add @nativescript-community/https
+```
+
+## Examples
+
+### Hitting an API using `GET` method
+
+```typescript
+import * as Https from '@nativescript-community/https';
+Https.request({
+ url: 'https://httpbin.org/get',
+ method: 'GET',
+ timeout: 30, // seconds (default 10)
+})
+ .then(function (response) {
+ console.log('Https.request response', response);
+ })
+ .catch(function (error) {
+ console.error('Https.request error', error);
+ });
+```
+
+## Configuration
+
+### Installing your SSL certificate
+
+Create a folder called `assets` in your projects `app` folder like so `/app/assets`. Using chrome, go to the URL where the SSL certificate resides. View the details then drag and drop the certificate image into the `assets` folder.
+
+
+
+#### Enabling SSL pinning
+
+```typescript
+import { knownFolders } from 'file-system';
+import * as Https from '@nativescript-community/https';
+let dir = knownFolders.currentApp().getFolder('assets');
+let certificate = dir.getFile('httpbin.org.cer').path;
+Https.enableSSLPinning({ host: 'httpbin.org', certificate });
+```
+
+Once you've enabled SSL pinning you **CAN NOT** re-enable with a different `host` or `certificate` file.
+
+#### Disabling SSL pinning
+
+```typescript
+import * as Https from '@nativescript-community/https';
+Https.disableSSLPinning();
+```
+
+All requests after calling this method will no longer utilize SSL pinning until it is re-enabled once again.
+
+### useLegacy
+
+There is a new option called `useLegacy`. You can set of every request options.
+When using that option the request will behave more like {N} http module.
+
+- the `content` returned by a request is not the resulting string but an object. It follows [HTTPContent](https://docs.nativescript.org/api-reference/interfaces/_http_.httpcontent) format for the most part. You can call `toJSON` or `toFile`. The only difference is that `toFile` returns a `Promise` which means that it is async and run in a background thread!
+- an error return a `content` too allowing you to read its content.
+
+### Cookie
+
+By default basic Cookie support is enabled to work like in {N} `http` module.
+In the future more options will be added
+
+### Enabling Cache
+
+```typescript
+import { knownFolders, path } from '@nativescript/core/file-system';
+import * as Https from '@nativescript-community/https';
+Https.setCache({
+ diskLocation: path.join(knownFolders.documents().path, 'httpcache'),
+ diskSize: 10 * 1024 * 1024, // 10 MiB
+});
+
+/// later on when calling your request you can use the cachePolicy option
+```
+
+### Multipart form data
+
+If you set the `Content-Type` header to `"multipart/form-data"` the request body will be evaluated as a multipart form data. Each body parameter is expected to be in this format:
+
+```typescript
+{
+ data: any
+ parameterName: string,
+ fileName?: string
+ contentType?: string
+}
+
+```
+
+if `fileName` and `contentType` are set then data is expected to be either a `NSData` on iOS or a `native.Array` on Android.
+
+### Options
+
+```typescript
+export interface HttpsSSLPinningOptions {
+ host: string;
+ certificate: string;
+ allowInvalidCertificates?: boolean;
+ validatesDomainName?: boolean;
+ commonName?: string;
+}
+import { HttpRequestOptions } from 'tns-core-modules/http';
+export interface HttpsRequestOptions extends HTTPOptions {
+ useLegacy?: boolean;
+ cachePolicy?: 'noCache' | 'onlyCache' | 'ignoreCache';
+ onProgress?: (current: number, total: number) => void;
+}
+```
+
+| SSLPinning Option | Description |
+| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
+| `host: string` | This must be the request domain name eg `sales.company.org`. |
+| `commonName?: string` | Default: options.host, set if certificate CN is different from the host eg `*.company.org` (Android specific) |
+| `certificate: string` | The uri path to your `.cer` certificate file. |
+| `allowInvalidCertificates?: boolean` | Default: `false`. This should **always** be `false` if you are using SSL pinning. Set this to `true` if you're using a self-signed certificate. |
+| `validatesDomainName?: boolean` | Default: `true`. Determines if the domain name should be validated with your pinned certificate. |
+
+| Requests Option | Description |
+| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `useLegacy?: boolean` | Default: `false`. [IOS only] set to true in order to get the response data (when status >= 300)in the `content` directly instead of `response.body.content`. |
+| `cachePolicy?: 'noCache' | 'onlyCache' | 'ignoreCache'` | Set the cache policy to use with that request. This only works with GET requests for now. |
+| `onProgress?: (current: number, total: number) => void` | [IOS only] Set the progress callback. |
+
+## Webpack / bundling
+
+Since you're probably shipping a certificate with your app (like [our demo does](https://github.com/nativescript-community/https/tree/master/demo/app/assets)),
+make sure it's bundled by Webpack as well. You can do this by [adding the certificate(s) with the `CopyWebpackPlugin`](https://github.com/nativescript-community/https/blob/a5c841c0af7ff6d9994fa23f7fba0df0514c58f1/demo/webpack.config.js#L240).
+
+## `iOS` Troubleshooting
+
+> ### Please educate yourself on iOS's [App Transport Security](https://github.com/codepath/ios_guides/wiki/App-Transport-Security) before starting beef!
+
+If you try and hit an `https` route without adding it to App Transport Security's whitelist it will not work!
+You can bypass this behavior by adding the following to your projects `Info.plist`:
+
+```xml
+NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+
+```
+
+> This plugin **does not** add `NSAllowsArbitraryLoads` to your projects `Info.plist` for you.
+
+## `Android` troubleshooting
+
+If you app crashes with a message that it's doing too much networking on the main thread,
+then pass the option `allowLargeResponse` with value `true` to the `request` function.
+
+# Thanks
+
+| Who | Why |
+| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [Robert Laverty](https://github.com/roblav96) | For creating and maintaining this plugin for a long time |
+| [Jeff Whelple](https://github.com/gethuman) | For contributing |
+| [Eddy Verbruggen](https://github.com/EddyVerbruggen) | For maintaining this before it got transferred |
+| [AFNetworking](https://github.com/AFNetworking) | [AFNetworking](https://github.com/AFNetworking/AFNetworking) A delightful networking framework for iOS, OS X, watchOS, and tvOS. |
+| [Square](http://square.github.io/) | [okhttp](https://github.com/square/okhttp) An HTTP+HTTP/2 client for Android and Java applications. |
+
+### Examples:
+
+- [Basic](demo-snippets/vue/Basic.vue)
+ - A basic example
+
+{{ load:../../tools/readme/demos-and-development.md }}
+{{ load:../../tools/readme/questions.md }}
\ No newline at end of file
diff --git a/packages/https/package.json b/packages/https/package.json
new file mode 100644
index 0000000..73c6b5e
--- /dev/null
+++ b/packages/https/package.json
@@ -0,0 +1,69 @@
+{
+ "name": "@nativescript-community/https",
+ "version": "4.1.32",
+ "description": "Nativescript plugin for https requests",
+ "main": "index",
+ "funding": "https://github.com/sponsors/farfromrefug",
+ "sideEffects": false,
+ "typings": "index.d.ts",
+ "nativescript": {
+ "platforms": {
+ "android": "6.2.1",
+ "ios": "6.2.1"
+ }
+ },
+ "scripts": {
+ "tsc": "cpy '**/*.d.ts' '../../packages/https' --parents --cwd=../../src/https && tsc --build",
+ "readme": "readme generate -c ../../tools/readme/blueprint.json",
+ "build": "npm run tsc && npm run readme",
+ "build.watch": "npm run tsc -- -w",
+ "build.win": "npm run tsc-win",
+ "build.all": "npm run build && npm run build.angular",
+ "build.angular": "ng-packagr -p ../../src/https/angular/ng-package.json -c ../../src/https/angular/tsconfig.json && rm angular/.npmignore",
+ "build.all.win": "npm run build.win",
+ "clean": "bin/rimraf ./*.d.ts ./*.js ./*.js.map ./*.tsbuildinfo ./*.mjs ./*.mjs.map ./angular ./svelte ./vue* ./react"
+ },
+ "contributors": [
+ {
+ "name": "Eddy Verbruggen",
+ "email": "eddyverbruggen@gmail.com",
+ "url": "https://github.com/EddyVerbruggen"
+ },
+ {
+ "name": "Kefah BADER ALDIN",
+ "email": "kefah.bader@gmail.com",
+ "url": "https://github.com/kefahB"
+ },
+ {
+ "name": "Ruslan Lekhman",
+ "email": "lekhman112@gmail.com",
+ "url": "https://github.com/lekhmanrus"
+ }
+ ],
+ "author": {
+ "name": "Martin Guillon",
+ "email": "dev@akylas.fr"
+ },
+ "bugs": {
+ "url": "https://github.com/nativescript-community/https/issues"
+ },
+ "license": "MIT",
+ "homepage": "https://github.com/nativescript-community/https",
+ "readmeFilename": "README.md",
+ "bootstrapper": "nativescript-plugin-seed",
+ "keywords": [
+ "secure",
+ "https",
+ "http",
+ "ssl",
+ "tls",
+ "pinning",
+ "nativescript",
+ "ecosystem:nativescript",
+ "nativescript-android",
+ "nativescript-ios",
+ "JavaScript",
+ "Android",
+ "iOS"
+ ]
+}
diff --git a/plugin/platforms/android/include.gradle b/packages/https/platforms/android/include.gradle
similarity index 91%
rename from plugin/platforms/android/include.gradle
rename to packages/https/platforms/android/include.gradle
index 6ab5dee..194baaa 100644
--- a/plugin/platforms/android/include.gradle
+++ b/packages/https/platforms/android/include.gradle
@@ -1,5 +1,5 @@
dependencies {
- def okHttpVersion = project.hasProperty("okHttpVersion") ? project.okHttpVersion : "3.14.7"
+ def okHttpVersion = project.hasProperty("okHttpVersion") ? project.okHttpVersion : "4.12.0"
implementation "com.squareup.okhttp3:okhttp:$okHttpVersion"
// def conscryptVersion = project.hasProperty("conscryptVersion") ? project.conscryptVersion : "2.4.0"
// implementation "org.conscrypt:conscrypt-android:$conscryptVersion"
diff --git a/packages/https/platforms/android/java/com/nativescript/https/CacheInterceptor.java b/packages/https/platforms/android/java/com/nativescript/https/CacheInterceptor.java
new file mode 100644
index 0000000..d7277df
--- /dev/null
+++ b/packages/https/platforms/android/java/com/nativescript/https/CacheInterceptor.java
@@ -0,0 +1,31 @@
+package com.nativescript.https;
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+import java.io.IOException;
+
+
+public class CacheInterceptor {
+ public static final Interceptor INTERCEPTOR = chain -> {
+ Request originalRequest = chain.request();
+ String cacheControlHeader = originalRequest.header("Cache-Control");
+ Response originalResponse = chain.proceed(originalRequest);
+
+ // Only touch GET responses
+ if (!"GET".equalsIgnoreCase(originalRequest.method())) {
+ return originalResponse;
+ }
+
+ String respCc = originalResponse.header("Cache-Control");
+ // If server didn't provide caching or forbids it, add a safe fallback
+ if (cacheControlHeader != null && (respCc == null || respCc.isEmpty() || respCc.contains("no-store") || respCc.contains("no-cache"))) {
+ // revalidate on network (max-age=0) but allow stale fallback if error
+ // stale-if-error may not be honored by everything but OkHttp will cache, enabling our fallback
+ return originalResponse.newBuilder()
+ .removeHeader("Pragma")
+ .header("Cache-Control", cacheControlHeader)
+ .build();
+ }
+ return originalResponse;
+ };
+}
\ No newline at end of file
diff --git a/packages/https/platforms/android/java/com/nativescript/https/CacheUtils.java b/packages/https/platforms/android/java/com/nativescript/https/CacheUtils.java
new file mode 100644
index 0000000..bfcbc96
--- /dev/null
+++ b/packages/https/platforms/android/java/com/nativescript/https/CacheUtils.java
@@ -0,0 +1,26 @@
+package com.nativescript.https;
+
+import java.util.Iterator;
+import okhttp3.Cache;
+
+public class CacheUtils {
+ public static void removeCachedResponse(String url, Cache cache) {
+ Iterator it;
+ try {
+ it = cache.urls();
+ } catch (Exception e) {
+ it = null;
+ }
+
+ if (it != null) {
+ while (it.hasNext()) {
+ String cacheUrl = it.next();
+
+ if (cacheUrl.equals(url)) {
+ it.remove();
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/plugin/platforms/android/java/com/nativescript/https/OkHttpResponse.java b/packages/https/platforms/android/java/com/nativescript/https/OkHttpResponse.java
similarity index 63%
rename from plugin/platforms/android/java/com/nativescript/https/OkHttpResponse.java
rename to packages/https/platforms/android/java/com/nativescript/https/OkHttpResponse.java
index 7da7bf5..0a9c682 100644
--- a/plugin/platforms/android/java/com/nativescript/https/OkHttpResponse.java
+++ b/packages/https/platforms/android/java/com/nativescript/https/OkHttpResponse.java
@@ -12,18 +12,70 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
import okhttp3.ResponseBody;
+import okhttp3.Response;
+import okhttp3.Headers;
+
+import org.json.JSONObject;
public class OkHttpResponse {
private final static String TAG = "OkHttpResponse";
- private ResponseBody responseBody;
static Handler mainHandler = null;
static boolean RUN_ON_MAIN_THREAD = true;
+ static boolean RUN_PROGRESS_ON_MAIN_THREAD = true;
public static final int DOWNLOAD_CHUNK_SIZE = 2048; // Same as Okio Segment.SIZE
+
+ private ResponseBody responseBody;
+ public boolean runOnMainThread = OkHttpResponse.RUN_ON_MAIN_THREAD;
+ public boolean runProgressOnMainThread = OkHttpResponse.RUN_PROGRESS_ON_MAIN_THREAD;
public OkHttpResponseProgressCallback progressCallback = null;
public OkHttpResponseCloseCallback closeCallback = null;
+ public static class ProgressInputStream extends InputStream {
+ private final InputStream inputStream;
+ private final ProgressListener listener;
+ private long totalBytesRead = 0;
+ private long contentLength = 0;
+
+ public interface ProgressListener {
+ void update(long bytesRead, long contentLength, boolean done);
+ }
+
+ public ProgressInputStream(InputStream inputStream, ProgressListener listener, long contentLength) {
+ this.inputStream = inputStream;
+ this.listener = listener;
+ this.contentLength = contentLength;
+ }
+
+ @Override
+ public int read() throws IOException {
+ int bytesRead = inputStream.read();
+ if (bytesRead >= 0) {
+ totalBytesRead++;
+ listener.update(totalBytesRead, contentLength, totalBytesRead == contentLength);
+ }
+ return bytesRead;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ int bytesRead = inputStream.read(b, off, len);
+ if (bytesRead >= 0) {
+ totalBytesRead += bytesRead;
+ listener.update(totalBytesRead, contentLength, totalBytesRead == contentLength);
+ }
+ return bytesRead;
+ }
+
+ @Override
+ public void close() throws IOException {
+ inputStream.close();
+ }
+ }
+
public static interface OkHttpResponseAsyncCallback {
void onException(final Exception exc);
@@ -43,6 +95,48 @@ public static interface OkHttpResponseProgressCallback {
public static interface OkHttpResponseCloseCallback {
void onClose();
}
+ private static class NotifyRunnable implements Runnable {
+ private final Runnable mRunnable;
+ private final Handler mHandler;
+ private boolean mFinished = false;
+
+ public NotifyRunnable(final Handler handler, final Runnable r) {
+ mRunnable = r;
+ mHandler = handler;
+ }
+
+ public boolean isFinished() {
+ return mFinished;
+ }
+
+ @Override
+ public void run() {
+ synchronized (mHandler) {
+ mRunnable.run();
+ mFinished = true;
+ mHandler.notifyAll();
+ }
+ }
+ }
+
+ public static void postAndWait(final Handler handler, final Runnable r) {
+
+ if (handler.getLooper() == Looper.myLooper()) {
+ r.run();
+ } else {
+ synchronized (handler) {
+ NotifyRunnable runnable = new NotifyRunnable(handler, r);
+ handler.post(runnable);
+ while (!runnable.isFinished()) {
+ try {
+ handler.wait();
+ } catch (InterruptedException is) {
+ // ignore
+ }
+ }
+ }
+ }
+ }
public OkHttpResponse(ResponseBody body) {
responseBody = body;
@@ -57,16 +151,20 @@ public long contentLength() {
return responseBody.contentLength();
}
- static void runProgressCallback(final OkHttpResponseProgressCallback progressCallback, final long current,
+ private static Handler getMainHandler() {
+ if (mainHandler == null) {
+ mainHandler = new Handler(android.os.Looper.getMainLooper());
+ }
+ return mainHandler;
+ }
+
+ private void runProgressCallback(final OkHttpResponseProgressCallback progressCallback, final long current,
final long total) {
if (progressCallback == null) {
return;
}
- if (RUN_ON_MAIN_THREAD) {
- if (mainHandler == null) {
- mainHandler = new Handler(android.os.Looper.getMainLooper());
- }
- mainHandler.post(new Runnable() {
+ if (runProgressOnMainThread) {
+ getMainHandler().post(new Runnable() {
@Override
public void run() {
progressCallback.onProgress(current, total);
@@ -77,15 +175,13 @@ public void run() {
}
}
- static void runCloseCallback(final OkHttpResponseCloseCallback closeCallback) {
+ private void runCloseCallback(final OkHttpResponseCloseCallback closeCallback) {
if (closeCallback == null) {
return;
}
- if (RUN_ON_MAIN_THREAD) {
- if (mainHandler == null) {
- mainHandler = new Handler(android.os.Looper.getMainLooper());
- }
- mainHandler.post(new Runnable() {
+ if (runOnMainThread) {
+
+ getMainHandler().post(new Runnable() {
@Override
public void run() {
closeCallback.onClose();
@@ -96,7 +192,7 @@ public void run() {
}
}
- static File responseBodyToFile(String filePath, OkHttpResponse response,
+ private File responseBodyToFile(String filePath, OkHttpResponse response,
OkHttpResponseProgressCallback progressCallback) throws Exception {
BufferedInputStream input = null;
OutputStream output = null;
@@ -147,7 +243,7 @@ private void closeResponseBody() {
closeResponseBody(responseBody, closeCallback);
}
- private static void closeResponseBody(ResponseBody responseBody, OkHttpResponseCloseCallback closeCallback) {
+ private void closeResponseBody(ResponseBody responseBody, OkHttpResponseCloseCallback closeCallback) {
responseBody.close();
runCloseCallback(closeCallback);
}
@@ -155,46 +251,27 @@ private static void closeResponseBody(ResponseBody responseBody, OkHttpResponseC
static Bitmap responseBodyToBitmap(OkHttpResponse response, OkHttpResponseProgressCallback progressCallback)
throws Exception {
- BufferedInputStream input = null;
- OutputStream output = null;
+ InputStream inputStream = null;
try {
- PipedInputStream in = new PipedInputStream();
- InputStream is = response.responseBody.byteStream();
- input = new BufferedInputStream(is);
-
- output = new PipedOutputStream(in);
-
- byte[] data = new byte[1024];
long contentLength = response.responseBody.contentLength();
-
- long total = 0;
- int count = 0;
- if (progressCallback != null) {
- progressCallback.onProgress(total, contentLength);
- }
- while ((count = input.read(data)) != -1 && !response.cancelled) {
- total += count;
- output.write(data, 0, count);
- if (progressCallback != null) {
- progressCallback.onProgress(total, contentLength);
+ inputStream = new ProgressInputStream(response.responseBody.byteStream(), new ProgressInputStream.ProgressListener() {
+ @Override
+ public void update(long bytesRead, long contentLength, boolean done) {
+ if (progressCallback != null) {
+ progressCallback.onProgress(bytesRead, contentLength);
+ }
}
- }
- if (response.cancelled && total != contentLength) {
- throw new Exception("cancelled");
- }
- return BitmapFactory.decodeStream(in);
+ }, contentLength);
+
+ // Decode the bitmap
+ return BitmapFactory.decodeStream(inputStream);
} catch (Exception e) {
throw e;
} finally {
- if (output != null) {
- output.flush();
- output.close();
+ if (inputStream != null) {
+ inputStream.close();
}
- if (input != null) {
- input.close();
- }
- input.close();
response.closeResponseBody();
}
}
@@ -205,18 +282,14 @@ public File toFile(String filePath) throws Exception {
public void toFileAsync(final String filePath, final OkHttpResponseAsyncCallback callback) {
final OkHttpResponse fme = this;
- // Log.d(TAG, "toFileAsync");
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
// Log.d(TAG, "toFileAsync run ");
final File result = responseBodyToFile(filePath, fme, progressCallback);
- if (RUN_ON_MAIN_THREAD) {
- if (mainHandler == null) {
- mainHandler = new Handler(android.os.Looper.getMainLooper());
- }
- mainHandler.post(new Runnable() {
+ if (runOnMainThread) {
+ getMainHandler().post(new Runnable() {
@Override
public void run() {
callback.onFile(result);
@@ -226,11 +299,8 @@ public void run() {
callback.onFile(result);
}
} catch (final Exception exc) {
- if (RUN_ON_MAIN_THREAD) {
- if (mainHandler == null) {
- mainHandler = new Handler(android.os.Looper.getMainLooper());
- }
- mainHandler.post(new Runnable() {
+ if (runOnMainThread) {
+ getMainHandler().post(new Runnable() {
@Override
public void run() {
callback.onException(exc);
@@ -267,11 +337,8 @@ public void toImageAsync(final OkHttpResponseAsyncCallback callback) {
public void run() {
try {
final Bitmap result = responseBodyToBitmap(fme, progressCallback);
- if (RUN_ON_MAIN_THREAD) {
- if (mainHandler == null) {
- mainHandler = new Handler(android.os.Looper.getMainLooper());
- }
- mainHandler.post(new Runnable() {
+ if (runOnMainThread) {
+ getMainHandler().post(new Runnable() {
@Override
public void run() {
callback.onBitmap(result);
@@ -281,11 +348,8 @@ public void run() {
callback.onBitmap(result);
}
} catch (final Exception exc) {
- if (RUN_ON_MAIN_THREAD) {
- if (mainHandler == null) {
- mainHandler = new Handler(android.os.Looper.getMainLooper());
- }
- mainHandler.post(new Runnable() {
+ if (runOnMainThread) {
+ getMainHandler().post(new Runnable() {
@Override
public void run() {
callback.onException(exc);
@@ -318,11 +382,8 @@ public void toByteArrayAsync(final OkHttpResponseAsyncCallback callback) {
public void run() {
try {
final java.nio.ByteBuffer result = responseBodyToByteArray(fme);
- if (RUN_ON_MAIN_THREAD) {
- if (mainHandler == null) {
- mainHandler = new Handler(android.os.Looper.getMainLooper());
- }
- mainHandler.post(new Runnable() {
+ if (runOnMainThread) {
+ getMainHandler().post(new Runnable() {
@Override
public void run() {
callback.onByteArray(result);
@@ -332,11 +393,8 @@ public void run() {
callback.onByteArray(result);
}
} catch (final Exception exc) {
- if (RUN_ON_MAIN_THREAD) {
- if (mainHandler == null) {
- mainHandler = new Handler(android.os.Looper.getMainLooper());
- }
- mainHandler.post(new Runnable() {
+ if (runOnMainThread) {
+ getMainHandler().post(new Runnable() {
@Override
public void run() {
callback.onException(exc);
@@ -369,11 +427,8 @@ public void asStringAsync(final OkHttpResponseAsyncCallback callback) {
public void run() {
try {
final String result = responseBodyToString(fme);
- if (RUN_ON_MAIN_THREAD) {
- if (mainHandler == null) {
- mainHandler = new Handler(android.os.Looper.getMainLooper());
- }
- mainHandler.post(new Runnable() {
+ if (runOnMainThread) {
+ getMainHandler().post(new Runnable() {
@Override
public void run() {
callback.onString(result);
@@ -383,11 +438,8 @@ public void run() {
callback.onString(result);
}
} catch (final Exception exc) {
- if (RUN_ON_MAIN_THREAD) {
- if (mainHandler == null) {
- mainHandler = new Handler(android.os.Looper.getMainLooper());
- }
- mainHandler.post(new Runnable() {
+ if (runOnMainThread) {
+ getMainHandler().post(new Runnable() {
@Override
public void run() {
callback.onException(exc);
@@ -401,4 +453,22 @@ public void run() {
});
thread.start();
}
-}
\ No newline at end of file
+ public static ResponseBody getBody(Response response) {
+ return response.body();
+ }
+ public static int getStatusCode(Response response) {
+ return response.code();
+ }
+ public static String getMessage(Response response) {
+ return response.message();
+ }
+ public static String getHeaders(Response response) throws Exception {
+ JSONObject obj = new JSONObject();
+ Headers headers = response.headers();
+ for (int i = 0; i < headers.size(); i++)
+ {
+ obj.put(headers.name(i), headers.value(i));
+ }
+ return obj.toString();
+ }
+}
diff --git a/plugin/platforms/android/java/com/nativescript/https/OkhttpCallback.java b/packages/https/platforms/android/java/com/nativescript/https/OkhttpCallback.java
similarity index 100%
rename from plugin/platforms/android/java/com/nativescript/https/OkhttpCallback.java
rename to packages/https/platforms/android/java/com/nativescript/https/OkhttpCallback.java
diff --git a/packages/https/platforms/android/java/com/nativescript/https/ProgressRequestWrapper.java b/packages/https/platforms/android/java/com/nativescript/https/ProgressRequestWrapper.java
new file mode 100644
index 0000000..86a7f3c
--- /dev/null
+++ b/packages/https/platforms/android/java/com/nativescript/https/ProgressRequestWrapper.java
@@ -0,0 +1,73 @@
+package com.nativescript.https;
+
+import okhttp3.RequestBody;
+import okhttp3.MediaType;
+
+import java.io.IOException;
+
+import okio.Buffer;
+import okio.BufferedSink;
+import okio.ForwardingSink;
+import okio.Okio;
+import okio.Sink;
+
+public class ProgressRequestWrapper extends RequestBody {
+
+ protected RequestBody delegate;
+ protected ProgressListener listener;
+
+ protected CountingSink countingSink;
+
+ public ProgressRequestWrapper(RequestBody delegate, ProgressListener listener) {
+ this.delegate = delegate;
+ this.listener = listener;
+ }
+
+ @Override
+ public MediaType contentType() {
+ return delegate.contentType();
+ }
+
+ @Override
+ public long contentLength() throws IOException {
+ return delegate.contentLength();
+ }
+
+ @Override
+ public void writeTo(BufferedSink sink) throws IOException {
+
+ BufferedSink bufferedSink;
+
+ countingSink = new CountingSink(sink);
+ bufferedSink = Okio.buffer(countingSink);
+
+ delegate.writeTo(bufferedSink);
+
+ bufferedSink.flush();
+ }
+
+ protected final class CountingSink extends ForwardingSink {
+
+ private long bytesWritten = 0;
+
+ public CountingSink(Sink delegate) {
+ super(delegate);
+ }
+
+ @Override
+ public void write(Buffer source, long byteCount) throws IOException {
+
+ super.write(source, byteCount);
+
+ bytesWritten += byteCount;
+ listener.onRequestProgress(bytesWritten, contentLength());
+ }
+
+ }
+
+ public interface ProgressListener {
+
+ void onRequestProgress(long bytesWritten, long contentLength);
+
+ }
+}
\ No newline at end of file
diff --git a/plugin/platforms/android/java/com/nativescript/https/QuotePreservingCookieJar.java b/packages/https/platforms/android/java/com/nativescript/https/QuotePreservingCookieJar.java
similarity index 66%
rename from plugin/platforms/android/java/com/nativescript/https/QuotePreservingCookieJar.java
rename to packages/https/platforms/android/java/com/nativescript/https/QuotePreservingCookieJar.java
index b8dcb17..34d87ed 100644
--- a/plugin/platforms/android/java/com/nativescript/https/QuotePreservingCookieJar.java
+++ b/packages/https/platforms/android/java/com/nativescript/https/QuotePreservingCookieJar.java
@@ -27,8 +27,6 @@
import okhttp3.HttpUrl;
import okhttp3.internal.platform.Platform;
-import static okhttp3.internal.Util.delimiterOffset;
-import static okhttp3.internal.Util.trimSubstring;
import static okhttp3.internal.platform.Platform.WARN;
/** A cookie jar that delegates to a {@link java.net.CookieHandler}. */
@@ -49,7 +47,7 @@ public QuotePreservingCookieJar(CookieHandler cookieHandler) {
try {
cookieHandler.put(url.uri(), multimap);
} catch (IOException e) {
- Platform.get().log(WARN, "Saving cookies failed for " + url.resolve("/..."), e);
+ // Platform.get().log(WARN, "Saving cookies failed for " + url.resolve("/..."), e);
}
}
}
@@ -61,7 +59,7 @@ public QuotePreservingCookieJar(CookieHandler cookieHandler) {
try {
cookieHeaders = cookieHandler.get(url.uri(), headers);
} catch (IOException e) {
- Platform.get().log(WARN, "Loading cookies failed for " + url.resolve("/..."), e);
+ // Platform.get().log(WARN, "Loading cookies failed for " + url.resolve("/..."), e);
return Collections.emptyList();
}
@@ -82,6 +80,64 @@ public QuotePreservingCookieJar(CookieHandler cookieHandler) {
: Collections.emptyList();
}
+ /**
+ * Increments {@code pos} until {@code input[pos]} is not ASCII whitespace. Stops at {@code
+ * limit}.
+ */
+ public static int skipLeadingAsciiWhitespace(String input, int pos, int limit) {
+ for (int i = pos; i < limit; i++) {
+ switch (input.charAt(i)) {
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ case ' ':
+ continue;
+ default:
+ return i;
+ }
+ }
+ return limit;
+ }
+
+ /**
+ * Decrements {@code limit} until {@code input[limit - 1]} is not ASCII whitespace. Stops at
+ * {@code pos}.
+ */
+ public static int skipTrailingAsciiWhitespace(String input, int pos, int limit) {
+ for (int i = limit - 1; i >= pos; i--) {
+ switch (input.charAt(i)) {
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ case ' ':
+ continue;
+ default:
+ return i + 1;
+ }
+ }
+ return pos;
+ }
+
+ /** Equivalent to {@code string.substring(pos, limit).trim()}. */
+ public static String trimSubstring(String string, int pos, int limit) {
+ int start = skipLeadingAsciiWhitespace(string, pos, limit);
+ int end = skipTrailingAsciiWhitespace(string, start, limit);
+ return string.substring(start, end);
+ }
+
+ /**
+ * Returns the index of the first character in {@code input} that contains a character in {@code
+ * delimiters}. Returns limit if there is no such character.
+ */
+ public static int delimiterOffset(String input, int pos, int limit, String delimiters) {
+ for (int i = pos; i < limit; i++) {
+ if (delimiters.indexOf(input.charAt(i)) != -1) return i;
+ }
+ return limit;
+ }
+
/**
* Convert a request header to OkHttp's cookies via {@link HttpCookie}. That extra step handles
* multiple cookies in a single request header, which {@link Cookie#parse} doesn't support.
@@ -90,7 +146,7 @@ private List decodeHeaderAsJavaNetCookies(HttpUrl url, String header) {
List result = new ArrayList<>();
for (int pos = 0, limit = header.length(), pairEnd; pos < limit; pos = pairEnd + 1) {
pairEnd = delimiterOffset(header, pos, limit, ";,");
- int equalsSign = delimiterOffset(header, pos, pairEnd, '=');
+ int equalsSign = delimiterOffset(header, pos, pairEnd, "=");
String name = trimSubstring(header, pos, equalsSign);
if (name.startsWith("$")) continue;
diff --git a/packages/https/platforms/android/native-api-usage.json b/packages/https/platforms/android/native-api-usage.json
new file mode 100644
index 0000000..f90d22f
--- /dev/null
+++ b/packages/https/platforms/android/native-api-usage.json
@@ -0,0 +1,43 @@
+{
+ "uses": [
+ "android.os:StrictMode",
+ "android.os:StrictMode.ThreadPolicy",
+ "okhttp3:Call",
+ "okhttp3:Dispatcher",
+ "okhttp3:RequestBody",
+ "okhttp3:MediaType",
+ "okhttp3:MultipartBody",
+ "okhttp3:Response",
+ "okhttp3:ResponseBody",
+ "okhttp3:Headers",
+ "okhttp3:MultipartBody.Builder",
+ "okhttp3:CacheControl",
+ "okhttp3:CacheControl.Builder",
+ "okhttp3:Request",
+ "okhttp3:Request.Builder",
+ "okhttp3:Interceptor",
+ "okhttp3:OkHttpClient",
+ "okhttp3:OkHttpClient.Builder",
+ "okhttp3:CertificatePinner",
+ "okhttp3:CertificatePinner.Builder",
+ "okhttp3:ConnectionSpec",
+ "okhttp3:Cache",
+ "okhttp3:Callback",
+ "okhttp3:FormBody",
+ "okhttp3:FormBody.Builder",
+ "okhttp3:CookieJar",
+ "java.net:CookieManager",
+ "java.net:CookiePolicy",
+ "com.nativescript.https*:*",
+ "java.util:Collections",
+ "java.security.cert:CertificateFactory",
+ "java.security:KeyStore",
+ "java.security:Security",
+ "javax.net.ssl:TrustManagerFactory",
+ "javax.net.ssl:SSLContext",
+ "javax.net.ssl:HttpsURLConnection",
+ "java.net:UnknownHostException",
+ "java.util.concurrent:TimeUnit",
+ "org.conscrypt:Conscrypt"
+ ]
+}
diff --git a/packages/https/platforms/ios/Podfile b/packages/https/platforms/ios/Podfile
new file mode 100644
index 0000000..9eec983
--- /dev/null
+++ b/packages/https/platforms/ios/Podfile
@@ -0,0 +1 @@
+pod 'AFNetworking', :git => 'https://github.com/nativescript-community/AFNetworking'
diff --git a/packages/https/tsconfig.json b/packages/https/tsconfig.json
new file mode 100644
index 0000000..3f53b42
--- /dev/null
+++ b/packages/https/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "rootDir": "../../src/https",
+ "outDir": "./"
+ },
+ "include": ["../../src/https/**/*", "../../references.d.ts", "../../tools/references.d.ts", "../../src/references.d.ts"],
+ "exclude": ["../../src/https/angular/**"]
+}
diff --git a/plugin/.npmignore b/plugin/.npmignore
deleted file mode 100644
index 25a243b..0000000
--- a/plugin/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-sync
-*.jar
-*.aar
diff --git a/plugin/CHANGELOG.md b/plugin/CHANGELOG.md
deleted file mode 100644
index 5c3d9e2..0000000
--- a/plugin/CHANGELOG.md
+++ /dev/null
@@ -1,109 +0,0 @@
-# Change Log
-
-All notable changes to this project will be documented in this file.
-See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
-
-## [3.3.2](https://github.com/farfromrefug/nativescript-https/compare/v3.3.1...v3.3.2) (2021-10-21)
-
-
-### Bug Fixes
-
-* **android:** native-api-usage fix ([6f8748d](https://github.com/farfromrefug/nativescript-https/commit/6f8748da0323eb2520dbb5024301deb136bd5baa))
-
-
-
-
-
-## [3.3.1](https://github.com/farfromrefug/nativescript-https/compare/v3.3.0...v3.3.1) (2021-10-18)
-
-
-### Bug Fixes
-
-* **android:** native-api-usage fix ([e18a203](https://github.com/farfromrefug/nativescript-https/commit/e18a2039464d488f3e370dd7feaf6ed61e4938e6))
-
-
-
-
-
-# [3.3.0](https://github.com/farfromrefug/nativescript-https/compare/v3.2.2...v3.3.0) (2021-10-17)
-
-
-### Bug Fixes
-
-* **android:** Conscrypt not included by default anymore. You need to add it in your app ([c16f34d](https://github.com/farfromrefug/nativescript-https/commit/c16f34d1b2f3fa226760ab00b17e56f6996dff96))
-
-
-### Features
-
-* **android:** native-api-usage ([9415f38](https://github.com/farfromrefug/nativescript-https/commit/9415f387b929b01c7fe385ff5d42e1bbd15ae2e4))
-
-
-
-
-
-## [3.2.2](https://github.com/farfromrefug/nativescript-https/compare/v3.2.1...v3.2.2) (2021-07-21)
-
-
-### Bug Fixes
-
-* **android:** prevent error when no cache-control ([e3d781e](https://github.com/farfromrefug/nativescript-https/commit/e3d781ed3a2d7364d3179d6a5acc39b5b9b65e29))
-
-
-
-
-
-## [3.2.1](https://github.com/farfromrefug/nativescript-https/compare/v3.2.0...v3.2.1) (2021-07-01)
-
-**Note:** Version bump only for package @nativescript-community/https
-
-
-
-
-
-# [3.2.0](https://github.com/farfromrefug/nativescript-https/compare/v3.1.3...v3.2.0) (2021-03-14)
-
-
-### Features
-
-* **android:** forceCache option ([cc225be](https://github.com/farfromrefug/nativescript-https/commit/cc225bea37e0035288533106e48a469e11d15d01))
-
-
-
-
-
-## [3.1.3](https://github.com/farfromrefug/nativescript-https/compare/v3.1.2...v3.1.3) (2021-03-12)
-
-**Note:** Version bump only for package @nativescript-community/https
-
-
-
-
-
-## [3.1.2](https://github.com/farfromrefug/nativescript-https/compare/v3.1.1...v3.1.2) (2020-12-09)
-
-
-### Bug Fixes
-
-* ios crash with cache on < 13 ([e021b8d](https://github.com/farfromrefug/nativescript-https/commit/e021b8d9c847f5ba545cc6fc52e6271780dd4e7f))
-
-
-
-
-
-## [3.1.1](https://github.com/farfromrefug/nativescript-https/compare/v3.1.0...v3.1.1) (2020-11-26)
-
-
-### Bug Fixes
-
-* correctly handle null responses from requests ([6b70be6](https://github.com/farfromrefug/nativescript-https/commit/6b70be64eb44a7e3da1705f025128bd9fabe6d2a))
-
-
-
-
-
-# 3.1.0 (2020-10-29)
-
-
-### Features
-
-* move to @nativescript-community/https ([5c8d5c8](https://github.com/farfromrefug/nativescript-https/commit/5c8d5c8c4e5e7d50a0312cf978638b6068398025))
diff --git a/plugin/package.json b/plugin/package.json
deleted file mode 100644
index 0e3f727..0000000
--- a/plugin/package.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "name": "@nativescript-community/https",
- "version": "3.3.2",
- "description": "Nativescript plugin for gestures",
- "main": "https",
- "sideEffects": false,
- "typings": "https.d.ts",
- "nativescript": {
- "platforms": {
- "android": "6.2.1",
- "ios": "6.2.1"
- }
- },
- "contributors": [
- {
- "name": "Robert Laverty",
- "email": "roblav96@gmail.com",
- "url": "https://github.com/roblav96"
- },
- {
- "name": "Kefah BADER ALDIN",
- "email": "kefah.bader@gmail.com",
- "url": "https://github.com/kefahB"
- }
- ],
- "author": "Eddy Verbruggen (https://github.com/EddyVerbruggen)",
- "bugs": {
- "url": "https://github.com/nativescript-community/https/issues"
- },
- "license": "MIT",
- "homepage": "https://github.com/nativescript-community/https",
- "readmeFilename": "README.md",
- "bootstrapper": "nativescript-plugin-seed",
- "keywords": [
- "secure",
- "https",
- "http",
- "ssl",
- "tls",
- "pinning",
- "nativescript",
- "ecosystem:nativescript",
- "nativescript-android",
- "nativescript-ios",
- "JavaScript",
- "Android",
- "iOS"
- ]
-}
diff --git a/plugin/platforms/android/java/com/nativescript/https/CacheInterceptor.java b/plugin/platforms/android/java/com/nativescript/https/CacheInterceptor.java
deleted file mode 100644
index 5d05571..0000000
--- a/plugin/platforms/android/java/com/nativescript/https/CacheInterceptor.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.nativescript.https;
-import okhttp3.Interceptor;
-import okhttp3.Request;
-import okhttp3.Response;
-import java.io.IOException;
-
-public class CacheInterceptor implements Interceptor {
- final String TAG = "CacheInterceptor";
-
- public Response intercept(Interceptor.Chain chain ) throws IOException {
- Request originalRequest = chain.request();
- String cacheControlHeader = originalRequest.header("Cache-Control");
- Response originalResponse = chain.proceed(originalRequest);
- if (cacheControlHeader != null) {
- return originalResponse.newBuilder().header("Cache-Control", cacheControlHeader).build();
- } else {
- return originalResponse;
- }
- }
-
-
-}
\ No newline at end of file
diff --git a/plugin/platforms/android/native-api-usage.json b/plugin/platforms/android/native-api-usage.json
deleted file mode 100644
index 9c49963..0000000
--- a/plugin/platforms/android/native-api-usage.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "uses": [
- "android.os:StrictMode*",
- "android.os.StrictMode:ThreadPolicy*",
- "okhttp3:Call*",
- "okhttp3:RequestBody*",
- "okhttp3:MediaType*",
- "okhttp3:MultipartBody*",
- "okhttp3:Response*",
- "okhttp3:ResponseBody*",
- "okhttp3:Headers*",
- "okhttp3.MultipartBody:Builder*",
- "okhttp3:CacheControl*",
- "okhttp3.CacheControl:Builder*",
- "okhttp3:Request*",
- "okhttp3.Request:Builder*",
- "okhttp3:OkHttpClient*",
- "okhttp3.OkHttpClient:Builder*",
- "okhttp3:CertificatePinner*",
- "okhttp3.CertificatePinner:Builder*",
- "okhttp3:ConnectionSpec*",
- "okhttp3:Cache*",
- "okhttp3:Callback*",
- "okhttp3:FormBody*",
- "okhttp3.FormBody:Builder*",
- "okhttp3:CookieJar*",
- "java.net:CookieManager*",
- "java.net:CookiePolicy*",
- "com.nativescript.https:QuotePreservingCookieJar*",
- "com.nativescript.https:CacheInterceptor*",
- "com.nativescript.https:OkHttpResponse*",
- "java.util:Collections*",
- "java.security.cert:CertificateFactory*",
- "java.security:KeyStore*",
- "java.security:Security*",
- "javax.net.ssl:TrustManagerFactory*",
- "javax.net.ssl:SSLContext*",
- "javax.net.ssl:HttpsURLConnection*",
- "java.util.concurrent:TimeUnit*",
- "org.conscrypt:Conscrypt*"
- ]
-}
\ No newline at end of file
diff --git a/plugin/platforms/ios/Podfile b/plugin/platforms/ios/Podfile
deleted file mode 100644
index 69e20bb..0000000
--- a/plugin/platforms/ios/Podfile
+++ /dev/null
@@ -1 +0,0 @@
-pod 'AFNetworking'
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..372bbfc
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,3 @@
+packages:
+ - packages/*
+ - demo-*
\ No newline at end of file
diff --git a/references.d.ts b/references.d.ts
index 15d1db6..e69de29 100644
--- a/references.d.ts
+++ b/references.d.ts
@@ -1,3 +0,0 @@
-///
-///
-///
diff --git a/src/https.android.ts b/src/https.android.ts
deleted file mode 100644
index 5d0ec53..0000000
--- a/src/https.android.ts
+++ /dev/null
@@ -1,537 +0,0 @@
-import { File, HttpResponseEncoding, ImageSource, Utils } from '@nativescript/core';
-import * as Https from './https.common';
-
-interface Ipeer {
- enabled: boolean;
- allowInvalidCertificates: boolean;
- validatesDomainName: boolean;
- host?: string;
- commonName?: string;
- certificate?: string;
- x509Certificate?: java.security.cert.Certificate;
-}
-
-const peer: Ipeer = {
- enabled: false,
- allowInvalidCertificates: false,
- validatesDomainName: true,
-};
-
-let cache: okhttp3.Cache;
-let forceCache = false;
-export function setCache(options?: Https.CacheOptions) {
- if (options) {
- forceCache = options.forceCache === true;
- cache = new okhttp3.Cache(new java.io.File(options.diskLocation), options.diskSize);
- } else {
- cache = null;
- }
- if (Client) {
- getClient(true);
- }
-}
-export function clearCache() {
- if (cache) {
- cache.evictAll();
- }
-}
-
-let _timeout = 10;
-
-class HttpsResponse implements Https.HttpsResponseLegacy {
- private callback?: com.nativescript.https.OkHttpResponse.OkHttpResponseAsyncCallback;
- constructor(private response: com.nativescript.https.OkHttpResponse, private tag: string, private url: string) {}
-
- getOrCreateCloseCallback() {
- if (!notClosedResponses[this.tag]) {
- // we need to store handling request to be able to cancel them
- notClosedResponses[this.tag] = this.response;
- this.response.closeCallback = new OkHttpResponse.OkHttpResponseCloseCallback({
- onClose() {
- delete notClosedResponses[this.tag];
- },
- });
- }
- }
- getCallback(resolve, reject) {
- return new com.nativescript.https.OkHttpResponse.OkHttpResponseAsyncCallback({
- onBitmap(res) {
- resolve(new ImageSource(res));
- },
- onString(res) {
- resolve(res);
- },
- onByteArray(res) {
- resolve((ArrayBuffer as any).from(res));
- },
- onFile(res) {
- resolve(res);
- },
- onException(err) {
- reject(err);
- },
- });
- }
-
- // cache it because asking it again wont work as the socket is closed
- arrayBuffer: ArrayBuffer;
- toArrayBuffer() {
- try {
- this.arrayBuffer = this.arrayBuffer || (ArrayBuffer as any).from(this.response.toByteArray());
- return this.arrayBuffer;
- } catch {
- return null;
- }
- }
- toArrayBufferAsync(): Promise {
- if (this.arrayBuffer) {
- return Promise.resolve(this.arrayBuffer);
- }
- return new Promise((resolve, reject) => {
- this.getOrCreateCloseCallback();
- this.response.toByteArrayAsync(this.getCallback(resolve, reject));
- }).then((r: ArrayBuffer) => {
- this.arrayBuffer = r;
- return this.arrayBuffer;
- });
- }
-
- // cache it because asking it again wont work as the socket is closed
- stringResponse: string;
- toString() {
- try {
- // TODO: handle arraybuffer already stored
- this.stringResponse = this.stringResponse || this.response.asString();
- return this.stringResponse;
- } catch {
- return null;
- }
- }
- async toStringAsync(): Promise {
- if (this.stringResponse) {
- return this.stringResponse;
- }
- // TODO: handle arraybuffer already stored
- this.stringResponse = await new Promise((resolve, reject) => {
- this.getOrCreateCloseCallback();
- this.response.asStringAsync(this.getCallback(resolve, reject));
- });
- return this.stringResponse;
- }
-
- // cache it because asking it again wont work as the socket is closed
- jsonResponse: any;
- toJSON(encoding?: HttpResponseEncoding) {
- try {
- if (this.jsonResponse !== undefined) {
- return this.jsonResponse;
- }
- // TODO: handle arraybuffer already stored
- this.stringResponse = this.stringResponse || this.response.asString();
- this.jsonResponse = this.stringResponse ? Https.parseJSON(this.stringResponse) : null;
- return this.jsonResponse;
- } catch (err) {
- console.error('HttpsResponse.toJSON', err);
- return null;
- }
- }
-
- async toJSONAsync() {
- if (this.jsonResponse !== undefined) {
- return this.jsonResponse;
- }
- if (this.stringResponse !== undefined) {
- this.jsonResponse = this.stringResponse ? Https.parseJSON(this.stringResponse) : null;
- return this.jsonResponse;
- }
- // TODO: handle arraybuffer already stored
- const r = await this.toStringAsync();
- this.jsonResponse = r ? Https.parseJSON(r) : null;
- return this.jsonResponse;
- }
-
- // cache it because asking it again wont work as the socket is closed
- imageSource: ImageSource;
- async toImage(): Promise {
- if (this.imageSource) {
- return this.imageSource;
- }
- return new Promise((resolve, reject) => {
- this.getOrCreateCloseCallback();
- this.response.toBitmapAsync(this.getCallback(resolve, reject)).then((r) => {
- this.imageSource = r;
- return r;
- });
- });
- }
- // toFile(destinationFilePath: string): File {
- // if (!destinationFilePath) {
- // destinationFilePath = Https.getFilenameFromUrl(this.url);
- // }
- // const file = this.response.toFile(destinationFilePath);
- // return File.fromPath(destinationFilePath);
- // }
- // cache it because asking it again wont work as the socket is closed
- file: File;
- toFile(destinationFilePath: string): Promise {
- if (this.file) {
- return Promise.resolve(this.file);
- }
- if (!destinationFilePath) {
- destinationFilePath = Https.getFilenameFromUrl(this.url);
- }
- return new Promise((resolve, reject) => {
- this.getOrCreateCloseCallback();
- this.response.toFileAsync(destinationFilePath, this.getCallback(resolve, reject));
- }).then(() => {
- this.file = File.fromPath(destinationFilePath);
- return this.file;
- });
- }
-}
-
-export function enableSSLPinning(options: Https.HttpsSSLPinningOptions) {
- if (!peer.host && !peer.certificate) {
- let certificate: string;
- let inputStream: java.io.FileInputStream;
- try {
- const file = new java.io.File(options.certificate);
- inputStream = new java.io.FileInputStream(file);
- const x509Certificate = java.security.cert.CertificateFactory.getInstance('X509').generateCertificate(inputStream);
- peer.x509Certificate = x509Certificate;
- certificate = okhttp3.CertificatePinner.pin(x509Certificate);
- inputStream.close();
- } catch (error) {
- try {
- if (inputStream) {
- inputStream.close();
- }
- } catch (e) {}
- console.error('@nativescript-community/https > enableSSLPinning error', error);
- return;
- }
- peer.host = options.host;
- peer.commonName = options.commonName || options.host;
- peer.certificate = certificate;
- if (options.allowInvalidCertificates === true) {
- peer.allowInvalidCertificates = true;
- }
- if (options.validatesDomainName === false) {
- peer.validatesDomainName = false;
- }
- }
- peer.enabled = true;
- getClient(true);
-}
-
-export function disableSSLPinning() {
- peer.enabled = false;
- getClient(true);
-}
-
-let Client: okhttp3.OkHttpClient;
-let cookieJar: com.nativescript.https.QuotePreservingCookieJar;
-let cookieManager: java.net.CookieManager;
-function getClient(reload: boolean = false, timeout: number = 10): okhttp3.OkHttpClient {
- if (!Client) {
- // ssl error fix on KitKat. Only need to be done once.
- // client will be null only onced so will run only once
- const version = android.os.Build.VERSION.SDK_INT;
- if (version >= 16 && version < 22 && (org as any).conscrypt) {
- java.security.Security.insertProviderAt((org as any).conscrypt.Conscrypt.newProvider(), 1);
- }
- }
- // if (!Client) {
- // Client = new okhttp3.OkHttpClient()
- // }
- // if (Client) {
- // Client.connectionPool().evictAll()
- // Client = null
- // }
- if (Client && reload === false) {
- if (timeout === _timeout) {
- return Client;
- } else {
- return Client.newBuilder()
- .connectTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS)
- .writeTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS)
- .readTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS)
- .build();
- }
- }
- if (!cookieJar) {
- cookieManager = new java.net.CookieManager();
- cookieManager.setCookiePolicy(java.net.CookiePolicy.ACCEPT_ALL);
- cookieJar = new com.nativescript.https.QuotePreservingCookieJar(cookieManager);
- }
-
- const client = new okhttp3.OkHttpClient.Builder();
- if (peer.enabled === true) {
- if (peer.host || peer.certificate) {
- const spec = okhttp3.ConnectionSpec.MODERN_TLS;
- client.connectionSpecs(java.util.Collections.singletonList(spec));
-
- const pinner = new okhttp3.CertificatePinner.Builder();
- pinner.add(peer.host, [peer.certificate]);
- client.certificatePinner(pinner.build());
-
- if (peer.allowInvalidCertificates === false) {
- try {
- const x509Certificate = peer.x509Certificate;
- const keyStore = java.security.KeyStore.getInstance(java.security.KeyStore.getDefaultType());
- keyStore.load(null, null);
- // keyStore.setCertificateEntry(peer.host, x509Certificate)
- keyStore.setCertificateEntry('CA', x509Certificate);
-
- // let keyManagerFactory = javax.net.ssl.KeyManagerFactory.getInstance(
- // javax.net.ssl.KeyManagerFactory.getDefaultAlgorithm()
- // )
- const keyManagerFactory = javax.net.ssl.KeyManagerFactory.getInstance('X509');
- keyManagerFactory.init(keyStore, null);
- const keyManagers = keyManagerFactory.getKeyManagers();
-
- const trustManagerFactory = javax.net.ssl.TrustManagerFactory.getInstance(javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm());
- trustManagerFactory.init(keyStore);
-
- const sslContext = javax.net.ssl.SSLContext.getInstance('TLS');
- sslContext.init(keyManagers, trustManagerFactory.getTrustManagers(), new java.security.SecureRandom());
- client.sslSocketFactory(sslContext.getSocketFactory());
- } catch (error) {
- console.error('@nativescript-community/https > client.allowInvalidCertificates error', error);
- }
- }
-
- if (peer.validatesDomainName === true) {
- try {
- client.hostnameVerifier(
- new javax.net.ssl.HostnameVerifier({
- verify: (hostname: string, session: javax.net.ssl.SSLSession): boolean => {
- const pp = session.getPeerPrincipal().getName();
- const hv = javax.net.ssl.HttpsURLConnection.getDefaultHostnameVerifier();
- if (peer.commonName && peer.commonName[0] === '*') {
- return hv.verify(peer.host, session) && hostname.indexOf(peer.host) > -1 && hostname.indexOf(session.getPeerHost()) > -1 && pp.indexOf(peer.commonName) !== -1;
- } else {
- return hv.verify(peer.host, session) && peer.host === hostname && peer.host === session.getPeerHost() && pp.indexOf(peer.host) !== -1;
- }
- },
- })
- );
- } catch (error) {
- console.error('@nativescript-community/https > client.validatesDomainName error', error);
- }
- }
- } else {
- console.warn('@nativescript-community/https > Undefined host or certificate. SSL pinning NOT working!!!');
- }
- }
-
- _timeout = timeout;
- client.connectTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS).writeTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS).readTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS);
-
- if (cache) {
- client.cache(cache);
- if (forceCache) {
- client.addInterceptor(new com.nativescript.https.CacheInterceptor());
- }
- }
- if (cookieJar) {
- client.cookieJar(cookieJar);
- }
-
- Client = client.build();
- return Client;
-}
-
-function cancelRequest(tag: string, client: okhttp3.OkHttpClient) {
- if (notClosedResponses[tag]) {
- notClosedResponses[tag].cancel();
- return;
- }
- const dispatcher = client.dispatcher();
- //When you want to cancel:
- //A) go through the queued calls and cancel if the tag matches:
- if (dispatcher.queuedCallsCount() > 0) {
- const queuedCalls = dispatcher.queuedCalls();
- for (let index = 0; index < queuedCalls.size(); index++) {
- const call = queuedCalls.get(index);
- if (call.request().tag() === tag) {
- call.cancel();
- return;
- }
- }
- }
-
- //B) go through the running calls and cancel if the tag matches:
- if (dispatcher.runningCallsCount() > 0) {
- const runningCalls = dispatcher.runningCalls();
- for (let index = 0; index < runningCalls.size(); index++) {
- const call = runningCalls.get(index);
- if (call.request().tag() === tag) {
- call.cancel();
- return;
- }
- }
- }
-}
-
-let CALL_ID = 0;
-const notClosedResponses: {
- [k: string]: com.nativescript.https.OkHttpResponse;
-} = {};
-let OkHttpResponse: typeof com.nativescript.https.OkHttpResponse;
-export function createRequest(opts: Https.HttpsRequestOptions): Https.HttpsRequest {
- const client = getClient(false, opts.timeout);
-
- const request = new okhttp3.Request.Builder();
- request.url(opts.url);
-
- if (opts.headers) {
- Object.keys(opts.headers).forEach((key) => request.addHeader(key, opts.headers[key] as any));
- }
-
- if (opts.cachePolicy) {
- let cacheControlBuilder = new okhttp3.CacheControl.Builder();
- switch (opts.cachePolicy) {
- case 'noCache':
- cacheControlBuilder = cacheControlBuilder.noStore();
- break;
- case 'onlyCache':
- cacheControlBuilder = cacheControlBuilder.onlyIfCached();
- break;
- case 'ignoreCache':
- cacheControlBuilder = cacheControlBuilder.noCache();
- break;
- }
- request.cacheControl(cacheControlBuilder.build());
- }
-
- const methods = {
- GET: 'get',
- HEAD: 'head',
- DELETE: 'delete',
- POST: 'post',
- PUT: 'put',
- PATCH: 'patch',
- };
- let type;
- if (['GET', 'HEAD'].indexOf(opts.method) !== -1 || (opts.method === 'DELETE' && !Utils.isDefined(opts.body) && !Utils.isDefined(opts.content))) {
- request[methods[opts.method]]();
- } else {
- type = opts.headers && opts.headers['Content-Type'] ? opts.headers['Content-Type'] : 'application/json';
- const MEDIA_TYPE = okhttp3.MediaType.parse(type);
- let okHttpBody: okhttp3.RequestBody;
- if (type.startsWith('multipart/form-data')) {
- const builder = new okhttp3.MultipartBody.Builder();
- builder.setType(MEDIA_TYPE);
-
- (opts.body as Https.HttpsFormDataParam[]).forEach((param) => {
- if (param.fileName && param.contentType) {
- const MEDIA_TYPE = okhttp3.MediaType.parse(param.contentType);
- builder.addFormDataPart(param.parameterName, param.fileName, okhttp3.RequestBody.create(MEDIA_TYPE, param.data));
- } else {
- builder.addFormDataPart(param.parameterName, param.data);
- }
- });
- okHttpBody = builder.build();
- } else if (type === 'application/x-www-form-urlencoded') {
- const builder = new okhttp3.FormBody.Builder();
- Object.keys(opts.body).forEach((key) => {
- builder.add(key, opts.body[key]);
- });
- okHttpBody = builder.build();
- } else {
- let body;
- if (opts.body) {
- try {
- body = JSON.stringify(opts.body);
- } catch (ignore) {}
- } else if (opts.content) {
- body = opts.content;
- }
- okHttpBody = okhttp3.RequestBody.create(okhttp3.MediaType.parse(type), body);
- }
- request[methods[opts.method]](okHttpBody);
- }
- const tag = `okhttp_request_${CALL_ID++}`;
- const call = client.newCall(request.tag(tag).build());
-
- // We have to allow networking on the main thread because larger responses will crash the app with an NetworkOnMainThreadException.
- // Note that it would probably be better to offload it to a Worker or (natively running) AsyncTask.
- // Also note that once set, this policy remains active until the app is killed.
- if (opts.useLegacy === false && opts.allowLargeResponse) {
- android.os.StrictMode.setThreadPolicy(android.os.StrictMode.ThreadPolicy.LAX);
- }
- return {
- nativeRequest: call,
- cancel: () => cancelRequest(tag, client),
- run(resolve, reject) {
- call.enqueue(
- new okhttp3.Callback({
- onResponse(call, response) {
- const responseBody = response.body();
- const message = response.message();
- const statusCode = response.code();
- const getHeaders = function () {
- const heads = response.headers();
- const headers = {};
- // let heads: okhttp3.Headers = resp.headers();
- const len: number = heads.size();
- let i: number;
- for (i = 0; i < len; i++) {
- const key = heads.name(i);
- headers[key] = heads.value(i);
- }
- return headers;
- };
- if (opts.useLegacy) {
- if (!OkHttpResponse) {
- OkHttpResponse = com.nativescript.https.OkHttpResponse;
- }
-
- const nResponse = new OkHttpResponse(responseBody);
-
- if (opts.onProgress) {
- nResponse.progressCallback = new OkHttpResponse.OkHttpResponseProgressCallback({
- onProgress: opts.onProgress,
- });
- }
-
- resolve({
- response,
- content: new HttpsResponse(nResponse, tag, opts.url),
- statusCode,
- reason: message,
- get headers() {
- return getHeaders();
- },
- });
- } else {
- resolve({
- response,
- content: responseBody.string(),
- reason: message,
- statusCode,
- get headers() {
- return getHeaders();
- },
- });
- }
- },
- onFailure(task, error) {
- reject(error);
- },
- })
- );
- },
- };
-}
-
-export function request(opts: Https.HttpsRequestOptions) {
- return new Promise((resolve, reject) => {
- try {
- createRequest(opts).run(resolve, reject);
- } catch (error) {
- reject(error);
- }
- });
-}
diff --git a/src/https.d.ts b/src/https.d.ts
deleted file mode 100644
index 484917e..0000000
--- a/src/https.d.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import * as Https from './https.common';
-
-export function enableSSLPinning(options: Https.HttpsSSLPinningOptions);
-
-export function disableSSLPinning();
-
-export function request(options: Https.HttpsRequestOptions): Promise;
-export function setCache(options?: Https.CacheOptions);
-export function clearCache();
-export function createRequest(opts: Https.HttpsRequestOptions): Https.HttpsRequest;
-
-export * from './https.common';
diff --git a/src/https/angular/excluded.service.ts b/src/https/angular/excluded.service.ts
new file mode 100644
index 0000000..c7384bb
--- /dev/null
+++ b/src/https/angular/excluded.service.ts
@@ -0,0 +1,24 @@
+import { Injectable } from '@angular/core';
+import { HttpRequest } from '@angular/common/http';
+
+@Injectable()
+export class ExcludedService {
+ private readonly _urlList: string[] = [];
+
+ public static isMultipartFormRequest(request: HttpRequest): boolean {
+ const headers = request.headers.get('Content-Type');
+ return headers ? headers.includes('application/x-www-form-urlencoded') : false;
+ }
+
+ public addUrl(domain: string): void {
+ this._urlList.push(domain);
+ }
+
+ public contains(needle: string): boolean {
+ return Boolean(this._urlList.filter((url) => url === needle).length);
+ }
+
+ public skipSslPinning(request: HttpRequest): boolean {
+ return this.contains(request.url);
+ }
+}
diff --git a/src/https/angular/index.ts b/src/https/angular/index.ts
new file mode 100644
index 0000000..085e332
--- /dev/null
+++ b/src/https/angular/index.ts
@@ -0,0 +1,2 @@
+export * from './ns-https.module';
+export * from './ns-http-xhr-backend';
diff --git a/src/https/angular/ng-package.json b/src/https/angular/ng-package.json
new file mode 100644
index 0000000..cdfd969
--- /dev/null
+++ b/src/https/angular/ng-package.json
@@ -0,0 +1,9 @@
+{
+ "dest": "../../../packages/https/angular",
+ "lib": {
+ "entryFile": "index.ts"
+ },
+ "allowedNonPeerDependencies": [
+ "."
+ ]
+}
diff --git a/src/https/angular/ns-http-xhr-backend.ts b/src/https/angular/ns-http-xhr-backend.ts
new file mode 100644
index 0000000..0eed719
--- /dev/null
+++ b/src/https/angular/ns-http-xhr-backend.ts
@@ -0,0 +1,128 @@
+import { Inject, Injectable, InjectionToken, Optional } from '@angular/core';
+import { XhrFactory } from '@angular/common';
+import { HttpErrorResponse, HttpEvent, HttpHeaders, HttpRequest, HttpResponse } from '@angular/common/http';
+import { Observable, from, throwError } from 'rxjs';
+import { catchError, map } from 'rxjs/operators';
+import { NSFileSystem, NsHttpBackEnd } from '@nativescript/angular';
+import { Headers, HttpsRequestObject, HttpsRequestOptions, HttpsResponse, request as httpsRequest } from '@nativescript-community/https';
+import { ExcludedService } from './excluded.service';
+
+/** Https request default options. */
+export type HttpsRequestDefaultOptions = Pick & { useLegacy?: boolean };
+
+/** Page size injection token. */
+export const HTTPS_REQUEST_DEFAULT_OPTIONS = new InjectionToken('HTTPS_REQUEST_DEFAULT_OPTIONS');
+
+@Injectable()
+export class NativeScriptHttpXhrBackend extends NsHttpBackEnd {
+ constructor(
+ xhrFactory: XhrFactory,
+ nsFileSystem: NSFileSystem,
+ private readonly _excludedService: ExcludedService,
+ @Optional()
+ @Inject(HTTPS_REQUEST_DEFAULT_OPTIONS)
+ private readonly _defaults?: HttpsRequestDefaultOptions
+ ) {
+ super(xhrFactory, nsFileSystem);
+ }
+
+ public handle(req: HttpRequest): Observable> {
+ let result: Observable>;
+ if (this._isLocalRequest(req.url) || this._excludedService.skipSslPinning(req)) {
+ result = super.handle(req);
+ } else {
+ result = this._request(req).pipe(
+ map((response: HttpsResponse) => {
+ if (response.statusCode < 200 || response.statusCode > 299) {
+ throw this._mapHttpErrorResponse(response, req);
+ }
+ return new HttpResponse({
+ body: response.content,
+ headers: new HttpHeaders(response.headers),
+ status: response.statusCode,
+ statusText: response.reason,
+ url: req.url
+ });
+ }),
+ catchError((error) => throwError(() => error))
+ );
+ }
+
+ return result;
+ }
+
+ private _isLocalRequest(url: string): boolean {
+ return url.indexOf('~') === 0 || url.indexOf('/') === 0;
+ }
+
+ private _request(request: HttpRequest) {
+ const method = request.method as 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD';
+ let url = request.url;
+ if (request.params) {
+ const params = request.params.toString();
+ if (params.length) {
+ const qIdx = url.indexOf('?');
+ const sep = qIdx === -1 ? '?' : (qIdx < url.length - 1 ? '&' : '');
+ url += sep + params;
+ }
+ }
+ return from(
+ httpsRequest(
+ {
+ url,
+ method,
+ headers: this._mapHeaders(request),
+ params: this._mapParams(request),
+ body: request.body,
+ timeout: this._defaults?.timeout ?? 3 * 60,
+ allowLargeResponse: this._defaults?.allowLargeResponse ?? true,
+ cachePolicy: this._defaults?.cachePolicy ?? 'noCache',
+ cookiesEnabled: this._defaults?.cookiesEnabled ?? false
+ },
+ this._defaults?.useLegacy ?? true
+ )
+ );
+ }
+
+ private _mapHeaders(request: HttpRequest): Headers {
+ const headerKeys = request.headers.keys();
+ const headers = headerKeys.reduce((accumulator, key) => {
+ const values = request.headers.getAll(key);
+ if (values !== null && values !== undefined) {
+ accumulator[key] = values.length > 1 ? values.join(' ') : values[0];
+ }
+ return accumulator;
+ }, {});
+
+ if (Object.keys(headers).length) {
+ return headers;
+ }
+
+ return {
+ 'Content-Type': 'application/json',
+ Accept: 'application/json'
+ };
+ }
+
+ private _mapParams(request: HttpRequest): HttpsRequestObject {
+ const paramKeys = request.params.keys();
+ const params = paramKeys.reduce((accumulator, key) => {
+ const values = request.params.getAll(key);
+ if (values !== null && values !== undefined) {
+ accumulator[key] = values.length > 1 ? values : values[0];
+ }
+ return accumulator;
+ }, {});
+ return params;
+ }
+
+ private _mapHttpErrorResponse(error: HttpsResponse, request: HttpRequest): HttpErrorResponse {
+ return new HttpErrorResponse({
+ error: error.content,
+ status: error.statusCode,
+ headers: new HttpHeaders(error.headers),
+ statusText: error.reason || (typeof error.content === 'string' && error.content) || String(error.statusCode),
+ url: request.url
+ });
+ }
+}
diff --git a/src/https/angular/ns-https.module.ts b/src/https/angular/ns-https.module.ts
new file mode 100644
index 0000000..b1533f9
--- /dev/null
+++ b/src/https/angular/ns-https.module.ts
@@ -0,0 +1,40 @@
+import { NgModule, ModuleWithProviders, Optional, Inject, InjectionToken } from '@angular/core';
+import { HttpBackend } from '@angular/common/http';
+import { NativeScriptHttpClientModule } from '@nativescript/angular';
+import { HttpsSSLPinningOptions, enableSSLPinning } from '@nativescript-community/https';
+import { HTTPS_REQUEST_DEFAULT_OPTIONS, NativeScriptHttpXhrBackend, HttpsRequestDefaultOptions } from './ns-http-xhr-backend';
+import { ExcludedService } from './excluded.service';
+
+/** Page size injection token. */
+export const HTTPS_SSL_PINNING_OPTIONS = new InjectionToken('HTTPS_SSL_PINNING_OPTIONS');
+
+@NgModule({
+ providers: [
+ ExcludedService,
+ NativeScriptHttpXhrBackend,
+ { provide: HttpBackend, useExisting: NativeScriptHttpXhrBackend },
+ { provide: HTTPS_REQUEST_DEFAULT_OPTIONS, useValue: {} },
+ { provide: HTTPS_SSL_PINNING_OPTIONS, useValue: { host: '', certificate: '' } }
+ ],
+ imports: [NativeScriptHttpClientModule],
+ exports: [NativeScriptHttpClientModule]
+})
+export class NativeScriptHttpsModule {
+ constructor(@Optional()@Inject(HTTPS_SSL_PINNING_OPTIONS) defaults?: HttpsSSLPinningOptions) {
+ enableSSLPinning(defaults ?? { host: '', certificate: '' });
+ }
+ /**
+ * Creates and configures a module.
+ * @param defaults Https request default options.
+ * @returns A wrapper around an NgModule that associates it with the providers.
+ */
+ static forRoot(defaults: HttpsRequestDefaultOptions & HttpsSSLPinningOptions = { host: '', certificate: '' }): ModuleWithProviders {
+ return {
+ ngModule: NativeScriptHttpsModule,
+ providers: [
+ { provide: HTTPS_REQUEST_DEFAULT_OPTIONS, useValue: defaults },
+ { provide: HTTPS_SSL_PINNING_OPTIONS, useValue: defaults }
+ ]
+ };
+ }
+}
diff --git a/src/https/angular/package.json b/src/https/angular/package.json
new file mode 100644
index 0000000..7908249
--- /dev/null
+++ b/src/https/angular/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "@nativescript-community/https-angular",
+ "main": "index.js"
+}
diff --git a/src/https/angular/tsconfig.json b/src/https/angular/tsconfig.json
new file mode 100644
index 0000000..202478a
--- /dev/null
+++ b/src/https/angular/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "extends": "../../../tsconfig.json",
+ "compilerOptions": {
+ "rootDir": "./",
+ "plugins": [],
+ "paths": {
+ "@nativescript-community/https": ["../../../packages/https"],
+ "@nativescript-community/https/*": ["../../../packages/https/*"]
+ }
+ },
+ "include": ["./**/*.ts", "../../../references.d.ts", "../references.d.ts"],
+ "exclude": ["../../../node_modules"],
+ "angularCompilerOptions": {
+ "enableIvy": true
+ }
+}
diff --git a/src/https/index.ts b/src/https/index.ts
new file mode 100644
index 0000000..250f64a
--- /dev/null
+++ b/src/https/index.ts
@@ -0,0 +1,51 @@
+import { ImageSource } from '@nativescript/core';
+import type { HttpsRequestOptions } from './request';
+// eslint-disable-next-line no-duplicate-imports
+import { request } from './request';
+export * from './request';
+
+/**
+ * Downloads the content from the specified URL as a string.
+ * @param arg either The URL to request from or HttpsRequestOptions options.
+ */
+export async function getString(arg: string | HttpsRequestOptions): Promise {
+ const r = await request(typeof arg === 'string' ? { url: arg, method: 'GET' } : arg);
+ return r.content.toStringAsync();
+}
+
+/**
+ * Downloads the content from the specified URL as a string and returns its JSON.parse representation.
+ * @param arg either The URL to request from or HttpsRequestOptions options.
+ */
+export async function getJSON(arg: string | HttpsRequestOptions): Promise {
+ const r = await request(typeof arg === 'string' ? { url: arg, method: 'GET' } : arg);
+ return r.content.toJSONAsync();
+}
+
+/**
+ * Downloads the content from the specified URL and attempts to decode it as an image.
+ * @param arg either The URL to request from or HttpsRequestOptions options.
+ */
+export async function getImage(arg: string | HttpsRequestOptions): Promise {
+ const r = await request(typeof arg === 'string' ? { url: arg, method: 'GET' } : arg);
+ return r.content.toImage();
+}
+
+/**
+ * Downloads the content from the specified URL and attempts to save it as file.
+ * @param arg either The URL to request from or HttpsRequestOptions options.
+ * @param destinationFilePath Optional. The downloaded file path.
+ */
+export async function getFile(arg: string | HttpsRequestOptions, destinationFilePath?: string): Promise {
+ const r = await request(typeof arg === 'string' ? { url: arg, method: 'GET' } : arg);
+ return r.content.toFile(destinationFilePath);
+}
+
+/**
+ * Downloads the content from the specified URL as binary and returns an ArrayBuffer.
+ * @param arg either The URL to request from or HttpsRequestOptions options.
+ */
+export async function getBinary(arg: string | HttpsRequestOptions): Promise {
+ const r = await request(typeof arg === 'string' ? { url: arg, method: 'GET' } : arg);
+ return r.content.toArrayBuffer();
+}
diff --git a/src/references.d.ts b/src/https/references.d.ts
similarity index 100%
rename from src/references.d.ts
rename to src/https/references.d.ts
diff --git a/src/https/request.android.ts b/src/https/request.android.ts
new file mode 100644
index 0000000..8dcbc8e
--- /dev/null
+++ b/src/https/request.android.ts
@@ -0,0 +1,675 @@
+import { File, HttpResponseEncoding, ImageSource, Utils } from '@nativescript/core';
+import { CacheOptions, HttpsFormDataParam, HttpsRequest, HttpsRequestOptions, HttpsSSLPinningOptions, HttpsResponseLegacy as IHttpsResponseLegacy } from '.';
+
+import { getFilenameFromUrl, interceptors, networkInterceptors, parseJSON } from './request.common';
+export { addNetworkInterceptor, addInterceptor } from './request.common';
+
+interface Ipeer {
+ enabled: boolean;
+ allowInvalidCertificates: boolean;
+ validatesDomainName: boolean;
+ host?: string;
+ commonName?: string;
+ certificate?: string;
+ x509Certificate?: java.security.cert.Certificate;
+}
+
+const peer: Ipeer = {
+ enabled: false,
+ allowInvalidCertificates: false,
+ validatesDomainName: true
+};
+
+let cache: okhttp3.Cache;
+let forceCache = false;
+
+export function setCache(options?: CacheOptions) {
+ if (options) {
+ forceCache = options.forceCache === true;
+ cache = new okhttp3.Cache(new java.io.File(options.diskLocation), options.diskSize);
+ } else {
+ cache = null;
+ }
+ if (Client) {
+ //we need to force a new client for the builder to use cache
+ getClient(undefined, true);
+ }
+}
+
+export function clearCache() {
+ if (cache) {
+ cache.evictAll();
+ }
+}
+
+export function removeCachedResponse(url: string) {
+ if (cache) {
+ com.nativescript.https.CacheUtils.removeCachedResponse(url, cache);
+ }
+}
+
+export function getManager() {
+ return getClient({}, false);
+}
+
+// TODO: rewrite this to not have to handle
+// every single property
+let _timeout = 10;
+let _cookiesEnabled = true;
+
+class HttpsResponseLegacy implements IHttpsResponseLegacy {
+ private callback?: com.nativescript.https.OkHttpResponse.OkHttpResponseAsyncCallback;
+ constructor(
+ private response: com.nativescript.https.OkHttpResponse,
+ private tag: string,
+ private url: string
+ ) {}
+
+ get contentLength() {
+ return this.response.contentLength();
+ }
+ getOrCreateCloseCallback() {
+ if (!notClosedResponses[this.tag]) {
+ // we need to store handling request to be able to cancel them
+ notClosedResponses[this.tag] = this.response;
+ this.response.closeCallback = new OkHttpResponse.OkHttpResponseCloseCallback({
+ onClose() {
+ delete notClosedResponses[this.tag];
+ }
+ });
+ }
+ }
+ getCallback(resolve, reject) {
+ return new com.nativescript.https.OkHttpResponse.OkHttpResponseAsyncCallback({
+ onBitmap(res) {
+ resolve(new ImageSource(res));
+ },
+ onString(res) {
+ resolve(res);
+ },
+ onByteArray(res) {
+ resolve((ArrayBuffer as any).from(res));
+ },
+ onFile(res) {
+ resolve(res);
+ },
+ onException(err) {
+ reject(err);
+ }
+ });
+ }
+
+ // cache it because asking it again wont work as the socket is closed
+ arrayBuffer: ArrayBuffer;
+ toArrayBuffer() {
+ try {
+ this.arrayBuffer = this.arrayBuffer || (ArrayBuffer as any).from(this.response.toByteArray());
+ return this.arrayBuffer;
+ } catch {
+ return null;
+ }
+ }
+ async toArrayBufferAsync() {
+ if (this.arrayBuffer) {
+ return Promise.resolve(this.arrayBuffer);
+ }
+ const r = await new Promise((resolve, reject) => {
+ this.getOrCreateCloseCallback();
+ this.response.toByteArrayAsync(this.getCallback(resolve, reject));
+ });
+ this.arrayBuffer = r;
+ return r;
+ }
+
+ // cache it because asking it again wont work as the socket is closed
+ stringResponse: string;
+ toString(encoding?: string) {
+ // TODO: handle arraybuffer already stored
+ this.stringResponse = this.stringResponse || this.response.asString();
+ return this.stringResponse;
+ }
+ async toStringAsync(encoding?: string): Promise {
+ if (this.stringResponse) {
+ return this.stringResponse;
+ }
+ // TODO: handle arraybuffer already stored
+ this.stringResponse = await new Promise((resolve, reject) => {
+ this.getOrCreateCloseCallback();
+ this.response.asStringAsync(this.getCallback(resolve, reject));
+ });
+ return this.stringResponse;
+ }
+
+ // cache it because asking it again wont work as the socket is closed
+ jsonResponse: any;
+ toJSON(encoding?: string) {
+ if (this.jsonResponse !== undefined) {
+ return this.jsonResponse;
+ }
+ // TODO: handle arraybuffer already stored
+ this.stringResponse = this.stringResponse || this.response.asString();
+ this.jsonResponse = this.stringResponse ? parseJSON(this.stringResponse) : null;
+ return this.jsonResponse;
+ }
+
+ async toJSONAsync() {
+ if (this.jsonResponse !== undefined) {
+ return this.jsonResponse;
+ }
+ if (this.stringResponse !== undefined) {
+ this.jsonResponse = this.stringResponse ? parseJSON(this.stringResponse) : null;
+ return this.jsonResponse;
+ }
+ // TODO: handle arraybuffer already stored
+ const r = await this.toStringAsync();
+ this.jsonResponse = r ? parseJSON(r) : null;
+ return this.jsonResponse as T;
+ }
+
+ // cache it because asking it again wont work as the socket is closed
+ imageSource: ImageSource;
+ async toImage(): Promise {
+ if (this.imageSource) {
+ return this.imageSource;
+ }
+ const r = await new Promise((resolve, reject) => {
+ this.getOrCreateCloseCallback();
+ this.response.toImageAsync(this.getCallback(resolve, reject));
+ });
+ this.imageSource = r;
+ return r;
+ }
+ // toFile(destinationFilePath: string): File {
+ // if (!destinationFilePath) {
+ // destinationFilePath = getFilenameFromUrl(this.url);
+ // }
+ // const file = this.response.toFile(destinationFilePath);
+ // return File.fromPath(destinationFilePath);
+ // }
+ // cache it because asking it again wont work as the socket is closed
+ file: File;
+ toFile(destinationFilePath: string): Promise {
+ if (this.file) {
+ return Promise.resolve(this.file);
+ }
+ if (!destinationFilePath) {
+ destinationFilePath = getFilenameFromUrl(this.url);
+ }
+ return new Promise((resolve, reject) => {
+ this.getOrCreateCloseCallback();
+ this.response.toFileAsync(destinationFilePath, this.getCallback(resolve, reject));
+ }).then(() => {
+ this.file = File.fromPath(destinationFilePath);
+ return this.file;
+ });
+ }
+}
+
+export function enableSSLPinning(options: HttpsSSLPinningOptions) {
+ if (!peer.host && !peer.certificate) {
+ let certificate: string;
+ let inputStream: java.io.FileInputStream;
+ try {
+ const file = new java.io.File(options.certificate);
+ inputStream = new java.io.FileInputStream(file);
+ const x509Certificate = java.security.cert.CertificateFactory.getInstance('X509').generateCertificate(inputStream);
+ peer.x509Certificate = x509Certificate;
+ certificate = okhttp3.CertificatePinner.pin(x509Certificate);
+ inputStream.close();
+ } catch (error) {
+ try {
+ if (inputStream) {
+ inputStream.close();
+ }
+ } catch (e) {}
+ console.error('@nativescript-community/https > enableSSLPinning error', error);
+ return;
+ }
+ peer.host = options.host;
+ peer.commonName = options.commonName || options.host;
+ peer.certificate = certificate;
+ if (options.allowInvalidCertificates === true) {
+ peer.allowInvalidCertificates = true;
+ }
+ if (options.validatesDomainName === false) {
+ peer.validatesDomainName = false;
+ }
+ }
+ peer.enabled = true;
+ getClient(undefined, true);
+}
+
+export function disableSSLPinning() {
+ peer.enabled = false;
+ getClient(undefined, true);
+}
+const SDKVersion = android.os.Build.VERSION.SDK_INT;
+
+let Client: okhttp3.OkHttpClient;
+let cookieJar: com.nativescript.https.QuotePreservingCookieJar;
+let cookieManager: java.net.CookieManager;
+export function getClient(opts: Partial = {}, reload: boolean = false): okhttp3.OkHttpClient {
+ if (!Client) {
+ // ssl error fix on KitKat. Only need to be done once.
+ // client will be null only onced so will run only once
+ if (SDKVersion >= 16 && SDKVersion < 22 && (org as any).conscrypt) {
+ java.security.Security.insertProviderAt((org as any).conscrypt.Conscrypt.newProvider(), 1);
+ }
+ }
+ // if (!Client) {
+ // Client = new okhttp3.OkHttpClient()
+ // }
+ // if (Client) {
+ // Client.connectionPool().evictAll()
+ // Client = null
+ // }
+ const timeout = opts.timeout ?? 10;
+ const cookiesEnabled = opts.cookiesEnabled ?? true;
+ if (Client && reload === false) {
+ const needTimeoutChange = timeout !== _timeout;
+ const needCookiesChange = cookiesEnabled === _cookiesEnabled;
+ if (!needTimeoutChange && !needCookiesChange) {
+ return Client;
+ } else {
+ const builder = Client.newBuilder();
+ if (needTimeoutChange) {
+ builder
+ .connectTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS)
+ .writeTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS)
+ .readTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS);
+ }
+ if (needCookiesChange) {
+ if (cookiesEnabled) {
+ if (!cookieJar) {
+ cookieManager = new java.net.CookieManager();
+ cookieManager.setCookiePolicy(java.net.CookiePolicy.ACCEPT_ALL);
+ cookieJar = new com.nativescript.https.QuotePreservingCookieJar(cookieManager);
+ }
+ builder.cookieJar(cookieJar);
+ } else {
+ // builder.cookieJar(null);
+ }
+ }
+ return builder.build();
+ }
+ }
+ const builder = new okhttp3.OkHttpClient.Builder();
+
+ _cookiesEnabled = cookiesEnabled;
+ if (cookiesEnabled) {
+ if (!cookieJar) {
+ cookieManager = new java.net.CookieManager();
+ cookieManager.setCookiePolicy(java.net.CookiePolicy.ACCEPT_ALL);
+ cookieJar = new com.nativescript.https.QuotePreservingCookieJar(cookieManager);
+ }
+ builder.cookieJar(cookieJar);
+ }
+
+ interceptors.forEach((interceptor) => builder.addInterceptor(interceptor));
+ networkInterceptors.forEach((interceptor) => builder.addNetworkInterceptor(interceptor));
+ if (peer.enabled === true) {
+ if (peer.host || peer.certificate) {
+ // const spec = okhttp3.ConnectionSpec.MODERN_TLS;
+ // builder.connectionSpecs(java.util.Collections.singletonList(spec));
+
+ const pinner = new okhttp3.CertificatePinner.Builder();
+ pinner.add(peer.host, [peer.certificate]);
+ builder.certificatePinner(pinner.build());
+
+ if (peer.allowInvalidCertificates === false) {
+ try {
+ const x509Certificate = peer.x509Certificate;
+ const keyStore = java.security.KeyStore.getInstance(java.security.KeyStore.getDefaultType());
+ keyStore.load(null, null);
+ // keyStore.setCertificateEntry(peer.host, x509Certificate)
+ keyStore.setCertificateEntry('CA', x509Certificate);
+
+ // let keyManagerFactory = javax.net.ssl.KeyManagerFactory.getInstance(
+ // javax.net.ssl.KeyManagerFactory.getDefaultAlgorithm()
+ // )
+ const keyManagerFactory = javax.net.ssl.KeyManagerFactory.getInstance('X509');
+ keyManagerFactory.init(keyStore, null);
+ const keyManagers = keyManagerFactory.getKeyManagers();
+
+ const trustManagerFactory = javax.net.ssl.TrustManagerFactory.getInstance(javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(keyStore);
+
+ const sslContext = javax.net.ssl.SSLContext.getInstance('TLS');
+ const trustManagers = trustManagerFactory.getTrustManagers();
+ if (trustManagers.length !== 1 || !(trustManagers[0] instanceof javax.net.ssl.X509TrustManager)) {
+ throw new Error('Unexpected default trust managers:' + trustManagers);
+ }
+ sslContext.init(keyManagers, trustManagers, null);
+ builder.sslSocketFactory(sslContext.getSocketFactory(), trustManagers[0]);
+ } catch (error) {
+ console.error('@nativescript-community/https > client.allowInvalidCertificates error', error);
+ }
+ }
+
+ if (peer.validatesDomainName === true) {
+ try {
+ builder.hostnameVerifier(
+ new javax.net.ssl.HostnameVerifier({
+ verify: (hostname: string, session: javax.net.ssl.SSLSession): boolean => {
+ const pp = session.getPeerPrincipal().getName();
+ const hv = javax.net.ssl.HttpsURLConnection.getDefaultHostnameVerifier();
+ if (peer.commonName && peer.commonName[0] === '*') {
+ return hv.verify(peer.host, session) && hostname.indexOf(peer.host) > -1 && hostname.indexOf(session.getPeerHost()) > -1 && pp.indexOf(peer.commonName) !== -1;
+ } else {
+ return hv.verify(peer.host, session) && peer.host === hostname && peer.host === session.getPeerHost() && pp.indexOf(peer.host) !== -1;
+ }
+ }
+ })
+ );
+ } catch (error) {
+ console.error('@nativescript-community/https > client.validatesDomainName error', error);
+ }
+ }
+ } else {
+ console.warn('@nativescript-community/https > Undefined host or certificate. SSL pinning NOT working!!!');
+ }
+ }
+
+ _timeout = timeout;
+ builder.connectTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS).writeTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS).readTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS);
+
+ if (cache) {
+ builder.cache(cache);
+ if (forceCache) {
+ builder.addInterceptor(com.nativescript.https.CacheInterceptor.INTERCEPTOR);
+ }
+ }
+
+ Client = builder.build();
+ return Client;
+}
+
+export function cancelRequest(tag: string, client: okhttp3.OkHttpClient = runningClients[tag]) {
+ if (notClosedResponses[tag]) {
+ notClosedResponses[tag].cancel();
+ return;
+ }
+ if (!client) {
+ return;
+ }
+ const dispatcher = client.dispatcher();
+ //When you want to cancel:
+ //A) go through the queued calls and cancel if the tag matches:
+ if (dispatcher.queuedCallsCount() > 0) {
+ const queuedCalls = dispatcher.queuedCalls();
+ for (let index = 0; index < queuedCalls.size(); index++) {
+ const call = queuedCalls.get(index);
+ if (call.request().tag() === tag) {
+ call.cancel();
+ return;
+ }
+ }
+ }
+
+ //B) go through the running calls and cancel if the tag matches:
+ if (dispatcher.runningCallsCount() > 0) {
+ const runningCalls = dispatcher.runningCalls();
+ for (let index = 0; index < runningCalls.size(); index++) {
+ const call = runningCalls.get(index);
+ if (call.request().tag() === tag) {
+ call.cancel();
+ return;
+ }
+ }
+ }
+}
+
+export function cancelAllRequests() {
+ Object.values(notClosedResponses).forEach((req) => req.cancel());
+
+ Object.values(runningClients).forEach((client) => {
+ const dispatcher = client.dispatcher();
+ //When you want to cancel:
+ //A) go through the queued calls and cancel if the tag matches:
+ if (dispatcher.queuedCallsCount() > 0) {
+ const queuedCalls = dispatcher.queuedCalls();
+ for (let index = 0; index < queuedCalls.size(); index++) {
+ const call = queuedCalls.get(index);
+ call.cancel();
+ }
+ }
+
+ //B) go through the running calls and cancel if the tag matches:
+ if (dispatcher.runningCallsCount() > 0) {
+ const runningCalls = dispatcher.runningCalls();
+ for (let index = 0; index < runningCalls.size(); index++) {
+ const call = runningCalls.get(index);
+ call.cancel();
+ }
+ }
+ });
+}
+
+export function clearCookies() {
+ if (cookieJar) {
+ cookieJar = null;
+ cookieManager = null;
+ }
+}
+
+let CALL_ID = 0;
+const notClosedResponses: {
+ [k: string]: com.nativescript.https.OkHttpResponse;
+} = {};
+
+const runningClients: { [k: string]: okhttp3.OkHttpClient } = {};
+
+let OkHttpResponse: typeof com.nativescript.https.OkHttpResponse;
+export function createRequest(opts: HttpsRequestOptions, useLegacy: boolean = true): HttpsRequest {
+ const client = getClient(opts, false);
+
+ const request = new okhttp3.Request.Builder();
+ request.url(opts.url);
+
+ if (opts.headers) {
+ Object.keys(opts.headers).forEach((key) => {
+ if (opts.headers[key]) {
+ request.addHeader(key, opts.headers[key] as any);
+ }
+ });
+ }
+
+ if (opts.cachePolicy) {
+ let cacheControlBuilder = new okhttp3.CacheControl.Builder();
+ switch (opts.cachePolicy) {
+ case 'noCache':
+ cacheControlBuilder = cacheControlBuilder.noStore();
+ break;
+ case 'onlyCache':
+ cacheControlBuilder = cacheControlBuilder.onlyIfCached();
+ break;
+ case 'ignoreCache':
+ cacheControlBuilder = cacheControlBuilder.noCache();
+ break;
+ }
+ request.cacheControl(cacheControlBuilder.build());
+ }
+
+ // const methods = {
+ // GET: 'get',
+ // HEAD: 'head',
+ // DELETE: 'delete',
+ // POST: 'post',
+ // PUT: 'put',
+ // PATCH: 'patch'
+ // };
+ // let type;
+ // if (['GET', 'HEAD'].indexOf(opts.method) !== -1 || (opts.method === 'DELETE' && !Utils.isDefined(opts.body) && !Utils.isDefined(opts.content))) {
+ // request[methods[opts.method]]();
+ // } else {
+ const type = opts.headers && opts.headers['Content-Type'] ? opts.headers['Content-Type'] : 'application/json';
+ const MEDIA_TYPE = okhttp3.MediaType.parse(type);
+ let okHttpBody: okhttp3.RequestBody;
+ if (type.startsWith('multipart/form-data')) {
+ const builder = new okhttp3.MultipartBody.Builder();
+ builder.setType(MEDIA_TYPE);
+
+ (opts.body as HttpsFormDataParam[]).forEach((param) => {
+ if (param.fileName && param.contentType) {
+ if (param.data instanceof okhttp3.RequestBody) {
+ builder.addFormDataPart(param.parameterName, param.fileName, param.data);
+ } else if (param.data instanceof File) {
+ builder.addFormDataPart(param.parameterName, param.fileName, okhttp3.RequestBody.create(new java.io.File(param.data.path), okhttp3.MediaType.parse(param.contentType)));
+ } else {
+ let nData = param.data;
+ if (param.data instanceof ArrayBuffer) {
+ const typedArray = new Uint8Array(param.data);
+ const nativeBuffer = java.nio.ByteBuffer.wrap(Array.from(typedArray));
+ nData = nativeBuffer.array();
+ } else if (typeof Blob !== 'undefined' && param.data instanceof Blob) {
+ // Stolen from core xhr, not sure if we should use InternalAccessor, but it provides fast access.
+ // @ts-ignore
+ const typedArray = new Uint8Array(Blob.InternalAccessor.getBuffer(param.data).buffer.slice(0) as ArrayBuffer);
+ const nativeBuffer = java.nio.ByteBuffer.wrap(Array.from(typedArray));
+ nData = nativeBuffer.array();
+ }
+ builder.addFormDataPart(param.parameterName, param.fileName, okhttp3.RequestBody.create(nData, okhttp3.MediaType.parse(param.contentType)));
+ }
+ } else {
+ if (typeof param.data === 'string') {
+ builder.addFormDataPart(param.parameterName, param.data);
+ } else {
+ builder.addFormDataPart(param.parameterName, param.data + '');
+ }
+ }
+ });
+ okHttpBody = builder.build();
+ } else if (type === 'application/x-www-form-urlencoded') {
+ const builder = new okhttp3.FormBody.Builder();
+ Object.keys(opts.body).forEach((key) => {
+ if (opts.body[key] !== undefined && opts.body[key] !== null) {
+ builder.add(key, opts.body[key]);
+ }
+ });
+ okHttpBody = builder.build();
+ } else {
+ let body;
+ if (opts.body) {
+ // TODO: add support for Buffers
+ if (opts.body instanceof File) {
+ okHttpBody = okhttp3.RequestBody.create(new java.io.File(opts.body.path), okhttp3.MediaType.parse(type));
+ } else if (typeof opts.body === 'string') {
+ body = opts.body;
+ } else {
+ try {
+ body = JSON.stringify(opts.body);
+ } catch (ignore) {}
+ }
+ } else if (opts.content) {
+ body = opts.content;
+ }
+ if (body instanceof okhttp3.RequestBody) {
+ okHttpBody = body;
+ } else if (body) {
+ okHttpBody = okhttp3.RequestBody.create(body, okhttp3.MediaType.parse(type));
+ }
+ }
+
+ if (okHttpBody && opts.onProgress) {
+ okHttpBody = new com.nativescript.https.ProgressRequestWrapper(
+ okHttpBody,
+ new com.nativescript.https.ProgressRequestWrapper.ProgressListener({
+ onRequestProgress(bytesWritten: number, contentLength: number) {
+ opts.onProgress(bytesWritten, contentLength);
+ }
+ })
+ );
+ }
+ request.method(opts.method, okHttpBody);
+ // request[methods[opts.method]](okHttpBody);
+ // }
+ const tag = opts.tag || `okhttp_request_${CALL_ID++}`;
+ const call = client.newCall(request.tag(tag).build());
+ runningClients[tag] = client;
+ // We have to allow networking on the main thread because larger responses will crash the app with an NetworkOnMainThreadException.
+ // Note that it would probably be better to offload it to a Worker or (natively running) AsyncTask.
+ // Also note that once set, this policy remains active until the app is killed.
+ if (useLegacy === false && opts.allowLargeResponse) {
+ android.os.StrictMode.setThreadPolicy(android.os.StrictMode.ThreadPolicy.LAX);
+ }
+ return {
+ nativeRequest: call,
+ cancel: () => cancelRequest(tag, client),
+ run(resolve, reject) {
+ call.enqueue(
+ new okhttp3.Callback({
+ onResponse(call, response) {
+ delete runningClients[tag];
+ if (!OkHttpResponse) {
+ OkHttpResponse = com.nativescript.https.OkHttpResponse;
+ }
+ try {
+ const responseBody = OkHttpResponse.getBody(response);
+ const message = OkHttpResponse.getMessage(response);
+ const statusCode = OkHttpResponse.getStatusCode(response);
+ const getHeaders = function () {
+ if (response) {
+ const heads = OkHttpResponse.getHeaders(response);
+ return JSON.parse(heads);
+ }
+ };
+ if (useLegacy) {
+ const nResponse = new OkHttpResponse(responseBody);
+ if (opts.responseOnMainThread === false) {
+ nResponse.runOnMainThread = false;
+ }
+ if (opts.progressOnMainThread === false || (opts.progressOnMainThread === undefined && opts.responseOnMainThread === false)) {
+ nResponse.runProgressOnMainThread = false;
+ }
+ if (opts.onProgress) {
+ nResponse.progressCallback = new OkHttpResponse.OkHttpResponseProgressCallback({
+ onProgress: opts.onProgress
+ });
+ }
+
+ resolve({
+ response,
+ content: new HttpsResponseLegacy(nResponse, tag, opts.url),
+ contentLength: nResponse.contentLength(),
+ statusCode,
+ reason: message,
+ get headers() {
+ return getHeaders();
+ }
+ });
+ } else {
+ resolve({
+ response,
+ content: responseBody.string(),
+ contentLength: responseBody.contentLength(),
+ reason: message,
+ statusCode,
+ get headers() {
+ return getHeaders();
+ }
+ });
+ }
+ } catch (error) {
+ delete runningClients[tag];
+ reject(error);
+ }
+ },
+ onFailure(task, error) {
+ delete runningClients[tag];
+ reject(error);
+ }
+ })
+ );
+ }
+ };
+}
+
+export function request(opts: HttpsRequestOptions, useLegacy: boolean = true) {
+ return new Promise((resolve, reject) => {
+ try {
+ createRequest(opts, useLegacy).run(resolve, reject);
+ } catch (error) {
+ reject(error);
+ }
+ });
+}
diff --git a/src/https/request.common.ts b/src/https/request.common.ts
new file mode 100644
index 0000000..23e1d29
--- /dev/null
+++ b/src/https/request.common.ts
@@ -0,0 +1,38 @@
+import { knownFolders, path } from '@nativescript/core';
+
+export function getFilenameFromUrl(url: string) {
+ const slashPos = url.lastIndexOf('/') + 1;
+ const questionMarkPos = url.lastIndexOf('?');
+
+ let actualFileName: string;
+ if (questionMarkPos !== -1) {
+ actualFileName = url.substring(slashPos, questionMarkPos);
+ } else {
+ actualFileName = url.substring(slashPos);
+ }
+
+ const result = path.join(knownFolders.documents().path, actualFileName);
+
+ return result;
+}
+
+export function parseJSON(source: string): any {
+ const src = source.trim();
+ if (src.lastIndexOf(')') === src.length - 1) {
+ return JSON.parse(src.substring(src.indexOf('(') + 1, src.lastIndexOf(')')));
+ }
+
+ return JSON.parse(src);
+}
+
+export const interceptors = [];
+
+export function addInterceptor(interceptor) {
+ interceptors.push(interceptor);
+}
+
+export const networkInterceptors = [];
+
+export function addNetworkInterceptor(interceptor) {
+ networkInterceptors.push(interceptor);
+}
diff --git a/src/https.common.ts b/src/https/request.d.ts
similarity index 50%
rename from src/https.common.ts
rename to src/https/request.d.ts
index 80e10be..24f1e91 100644
--- a/src/https.common.ts
+++ b/src/https/request.d.ts
@@ -1,4 +1,7 @@
-import { File, Headers, HttpRequestOptions, ImageSource, knownFolders, path } from '@nativescript/core';
+import { File, HttpRequestOptions, ImageSource } from '@nativescript/core';
+import * as Https from './request.common';
+
+export function getManager(): any; // okhttp3.OkHttpClient or AFHTTPSessionManager
export interface HttpsSSLPinningOptions {
host: string;
@@ -25,14 +28,22 @@ export interface HttpsRequestObject {
[key: string]: string | number | boolean | HttpsRequestObject | any[] | HttpsFormDataParam;
}
+export interface Headers {
+ [k: string]: string;
+}
+
export type CachePolicy = 'noCache' | 'onlyCache' | 'ignoreCache';
export interface HttpsRequestOptions extends HttpRequestOptions {
url: string;
- method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD';
+ tag?: string; // optional request tag to allow to cancel it
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
headers?: Headers;
params?: HttpsRequestObject;
- body?: HttpsRequestObject | HttpsFormDataParam[];
- content?: string;
+ body?: HttpsRequestObject | HttpsFormDataParam[] | File;
+ /**
+ * content can be used to pass native custom okhttp3.RequestBody
+ */
+ content?: string | any;
/**
* Default 10 (seconds).
*/
@@ -50,14 +61,26 @@ export interface HttpsRequestOptions extends HttpRequestOptions {
*/
onProgress?: (current: number, total: number) => void;
+ /**
+ * default to true. Put to false to run response callback on current thread
+ */
+ responseOnMainThread?: boolean;
+ progressOnMainThread?: boolean;
+
cachePolicy?: CachePolicy;
- useLegacy?: boolean;
+
+ /**
+ * default to true. Android and iOS only store cookies in memory! it will be cleared after an app restart
+ */
+ cookiesEnabled?: boolean;
}
-export interface HttpsResponse {
+export interface HttpsResponse {
headers?: Headers;
statusCode?: number;
- content?: any;
+ contentLength: number;
+ content?: T;
+ response?: string;
reason?: string;
description?: string;
url?: string;
@@ -70,40 +93,38 @@ export interface HttpsRequest {
run(success, failure);
}
-export interface HttpsResponseLegacy {
+export interface HttpsResponseLegacy {
+ contentLength: number;
toArrayBuffer(): ArrayBuffer;
toArrayBufferAsync(): Promise;
toString(): string;
toStringAsync(): Promise;
- toJSON(): any;
- toJSONAsync(): Promise;
+ toJSON(): T;
+ toJSONAsync(): Promise;
toImage(): Promise;
// toImageAsync(): Promise;
toFile(destinationFilePath: string): Promise;
// toFileAsync(destinationFilePath: string): Promise;
}
-export function getFilenameFromUrl(url: string) {
- const slashPos = url.lastIndexOf('/') + 1;
- const questionMarkPos = url.lastIndexOf('?');
-
- let actualFileName: string;
- if (questionMarkPos !== -1) {
- actualFileName = url.substring(slashPos, questionMarkPos);
- } else {
- actualFileName = url.substring(slashPos);
- }
-
- const result = path.join(knownFolders.documents().path, actualFileName);
-
- return result;
-}
-export function parseJSON(source: string): any {
- const src = source.trim();
- if (src.lastIndexOf(')') === src.length - 1) {
- return JSON.parse(src.substring(src.indexOf('(') + 1, src.lastIndexOf(')')));
- }
-
- return JSON.parse(src);
-}
+export function enableSSLPinning(options: HttpsSSLPinningOptions);
+
+export function disableSSLPinning();
+
+// export declare function request(options: HttpsRequestOptions): Promise>>;
+export declare function request(
+ options: HttpsRequestOptions,
+ useLegacy?: U
+): U extends true ? Promise>> : Promise>;
+export function setCache(options?: CacheOptions);
+export function clearCache();
+export function removeCachedResponse(url: string);
+export function createRequest(opts: HttpsRequestOptions): HttpsRequest;
+export function cancelRequest(tag: string);
+export function cancelAllRequests();
+export function clearCookies();
+export function addNetworkInterceptor(interceptor);
+
+export function getClient(opts: Partial);
+export * from './request.common';
diff --git a/src/https.ios.ts b/src/https/request.ios.ts
similarity index 55%
rename from src/https.ios.ts
rename to src/https/request.ios.ts
index b7555b2..cb9c105 100644
--- a/src/https.ios.ts
+++ b/src/https/request.ios.ts
@@ -1,9 +1,11 @@
import { File, ImageSource, Utils } from '@nativescript/core';
-import * as Https from './https.common';
+import { CacheOptions, HttpsFormDataParam, HttpsRequest, HttpsRequestOptions, HttpsResponse, HttpsSSLPinningOptions, HttpsResponseLegacy as IHttpsResponseLegacy } from '.';
+import { getFilenameFromUrl, parseJSON } from './request.common';
+export { addInterceptor, addNetworkInterceptor } from './request.common';
let cache: NSURLCache;
-export function setCache(options?: Https.CacheOptions) {
+export function setCache(options?: CacheOptions) {
if (options) {
cache = NSURLCache.alloc().initWithMemoryCapacityDiskCapacityDiskPath(options.memorySize, options.diskSize, options.diskLocation);
} else {
@@ -11,10 +13,15 @@ export function setCache(options?: Https.CacheOptions) {
}
NSURLCache.sharedURLCache = cache;
}
+
export function clearCache() {
NSURLCache.sharedURLCache.removeAllCachedResponses();
}
+export function removeCachedResponse(url: string) {
+ NSURLCache.sharedURLCache.removeCachedResponseForRequest(createNSRequest(url));
+}
+
interface Ipolicies {
def: AFSecurityPolicy;
secured: boolean;
@@ -23,13 +30,22 @@ interface Ipolicies {
const policies: Ipolicies = {
def: AFSecurityPolicy.defaultPolicy(),
- secured: false,
+ secured: false
};
policies.def.allowInvalidCertificates = true;
policies.def.validatesDomainName = false;
-export function enableSSLPinning(options: Https.HttpsSSLPinningOptions) {
+const configuration = NSURLSessionConfiguration.defaultSessionConfiguration;
+let manager = AFHTTPSessionManager.alloc().initWithSessionConfiguration(configuration);
+
+export function getManager(): AFHTTPSessionManager {
+ return manager;
+}
+
+export function enableSSLPinning(options: HttpsSSLPinningOptions) {
+ const url = NSURL.URLWithString(options.host);
+ manager = AFHTTPSessionManager.alloc().initWithSessionConfiguration(configuration).initWithBaseURL(url);
if (!policies.secure) {
policies.secure = AFSecurityPolicy.policyWithPinningMode(AFSSLPinningMode.PublicKey);
policies.secure.allowInvalidCertificates = Utils.isDefined(options.allowInvalidCertificates) ? options.allowInvalidCertificates : false;
@@ -44,35 +60,38 @@ export function disableSSLPinning() {
policies.secured = false;
}
-function nativeToObj(data) {
+function nativeToObj(data, encoding?) {
let content: any;
if (data instanceof NSDictionary) {
content = {};
data.enumerateKeysAndObjectsUsingBlock((key, value, stop) => {
- content[key] = nativeToObj(value);
+ content[key] = nativeToObj(value, encoding);
});
return content;
} else if (data instanceof NSArray) {
content = [];
data.enumerateObjectsUsingBlock((value, index, stop) => {
- content[index] = nativeToObj(value);
+ content[index] = nativeToObj(value, encoding);
});
return content;
} else if (data instanceof NSData) {
- return NSString.alloc().initWithDataEncoding(data, NSASCIIStringEncoding).toString();
+ return NSString.alloc()
+ .initWithDataEncoding(data, encoding === 'ascii' ? NSASCIIStringEncoding : NSUTF8StringEncoding)
+ .toString();
} else {
return data;
}
}
-function getData(data) {
+function getData(data, encoding?) {
let content: any;
if (data && data.class) {
+ const nEncoding = encoding === 'ascii' ? NSASCIIStringEncoding : NSUTF8StringEncoding;
if (data.enumerateKeysAndObjectsUsingBlock || data instanceof NSArray) {
const serial = NSJSONSerialization.dataWithJSONObjectOptionsError(data, NSJSONWritingOptions.PrettyPrinted);
- content = NSString.alloc().initWithDataEncoding(serial, NSUTF8StringEncoding).toString();
+ content = NSString.alloc().initWithDataEncoding(serial, nEncoding)?.toString();
} else if (data instanceof NSData) {
- content = NSString.alloc().initWithDataEncoding(data, NSASCIIStringEncoding).toString();
+ content = NSString.alloc().initWithDataEncoding(data, nEncoding)?.toString();
} else {
content = data;
}
@@ -88,9 +107,17 @@ function getData(data) {
return content;
}
-class HttpsResponse implements Https.HttpsResponseLegacy {
+function createNSRequest(url: string): NSMutableURLRequest {
+ return NSMutableURLRequest.alloc().initWithURL(NSURL.URLWithString(url));
+}
+
+class HttpsResponseLegacy implements IHttpsResponseLegacy {
// private callback?: com.nativescript.https.OkhttpResponse.OkHttpResponseAsyncCallback;
- constructor(private data: NSDictionary & NSData & NSArray, private url: string) {}
+ constructor(
+ private data: NSDictionary & NSData & NSArray,
+ public contentLength,
+ private url: string
+ ) {}
toArrayBufferAsync(): Promise {
throw new Error('Method not implemented.');
}
@@ -126,7 +153,7 @@ class HttpsResponse implements Https.HttpsResponseLegacy {
this.stringResponse = this.data;
return this.data;
} else {
- const data = nativeToObj(this.data);
+ const data = nativeToObj(this.data, encoding);
if (typeof data === 'string') {
this.stringResponse = data;
} else {
@@ -140,7 +167,7 @@ class HttpsResponse implements Https.HttpsResponseLegacy {
return Promise.resolve(this.toString(encoding));
}
jsonResponse: any;
- toJSON(encoding?: any) {
+ toJSON(encoding?: any) {
if (!this.data) {
return null;
}
@@ -148,35 +175,30 @@ class HttpsResponse implements Https.HttpsResponseLegacy {
return this.jsonResponse;
}
if (this.stringResponse) {
- this.jsonResponse = Https.parseJSON(this.stringResponse);
+ this.jsonResponse = parseJSON(this.stringResponse);
return this.jsonResponse;
}
- const data = nativeToObj(this.data);
+ const data = nativeToObj(this.data, encoding);
if (typeof data === 'object') {
this.jsonResponse = data;
return data;
}
- try {
- this.stringResponse = data;
- this.jsonResponse = Https.parseJSON(data);
- return this.jsonResponse;
- } catch (err) {
- console.error('HttpsResponse.toJSON', err);
- return null;
- }
+ this.stringResponse = data;
+ this.jsonResponse = data ? parseJSON(data) : null;
+ return this.jsonResponse as T;
}
- toJSONAsync(): Promise {
- return Promise.resolve(this.toJSON());
+ toJSONAsync() {
+ return Promise.resolve(this.toJSON());
}
imageSource: ImageSource;
- toImage(): Promise {
+ async toImage(): Promise {
if (!this.data) {
return Promise.resolve(null);
}
if (this.imageSource) {
return Promise.resolve(this.imageSource);
}
- return new Promise((resolve, reject) => {
+ const r = await new Promise((resolve, reject) => {
(UIImage as any).tns_decodeImageWithDataCompletion(this.data, (image) => {
if (image) {
resolve(new ImageSource(image));
@@ -184,29 +206,28 @@ class HttpsResponse implements Https.HttpsResponseLegacy {
reject(new Error('Response content may not be converted to an Image'));
}
});
- }).then((r) => {
- this.imageSource = r;
- return r;
});
+ this.imageSource = r;
+ return r;
}
file: File;
- toFile(destinationFilePath?: string): Promise {
+ async toFile(destinationFilePath?: string): Promise {
if (!this.data) {
return Promise.resolve(null);
}
if (this.file) {
return Promise.resolve(this.file);
}
- return new Promise((resolve, reject) => {
+ const r = await new Promise((resolve, reject) => {
if (!destinationFilePath) {
- destinationFilePath = Https.getFilenameFromUrl(this.url);
+ destinationFilePath = getFilenameFromUrl(this.url);
}
if (this.data instanceof NSData) {
// ensure destination path exists by creating any missing parent directories
const file = File.fromPath(destinationFilePath);
const result = this.data.writeToFileAtomically(destinationFilePath, true);
- if (resolve) {
+ if (result) {
resolve(file);
} else {
reject(new Error(`Cannot save file with path: ${destinationFilePath}.`));
@@ -214,25 +235,25 @@ class HttpsResponse implements Https.HttpsResponseLegacy {
} else {
reject(new Error(`Cannot save file with path: ${destinationFilePath}.`));
}
- }).then((f) => {
- this.file = f;
- return f;
});
+ this.file = r;
+ return r;
}
}
function AFFailure(resolve, reject, task: NSURLSessionDataTask, error: NSError, useLegacy: boolean, url) {
if (error.code === -999) {
- return reject(new Error(error.localizedDescription));
+ return reject(error);
}
let getHeaders = () => ({});
const sendi = {
task,
+ contentLength: task?.countOfBytesReceived,
reason: error.localizedDescription,
get headers() {
return getHeaders();
- },
- } as Https.HttpsResponse;
+ }
+ } as any as HttpsResponse;
const response = error.userInfo.valueForKey(AFNetworkingOperationFailingURLResponseErrorKey) as NSHTTPURLResponse;
if (!Utils.isNullOrUndefined(response)) {
sendi.statusCode = response.statusCode;
@@ -252,31 +273,35 @@ function AFFailure(resolve, reject, task: NSURLSessionDataTask, error: NSError,
const failingURL = error.userInfo.objectForKey('NSErrorFailingURLKey');
if (useLegacy) {
if (!sendi.statusCode) {
- return reject(error.localizedDescription);
+ return reject(error);
}
const failure: any = {
+ error,
description: error.description,
reason: error.localizedDescription,
- url: failingURL ? failingURL.description : url,
+ url: failingURL ? failingURL.description : url
};
if (policies.secured === true) {
failure.description = '@nativescript-community/https > Invalid SSL certificate! ' + error.description;
}
sendi.failure = failure;
- sendi.content = new HttpsResponse(data, url);
+ sendi.content = new HttpsResponseLegacy(data, sendi.contentLength, url);
resolve(sendi);
} else {
- const content: any = {
+ const response: any = {
+ error,
body: parsedData,
+ contentLength: sendi.contentLength,
description: error.description,
reason: error.localizedDescription,
- url: failingURL ? failingURL.description : url,
+ url: failingURL ? failingURL.description : url
};
if (policies.secured === true) {
- content.description = '@nativescript-community/https > Invalid SSL certificate! ' + content.description;
+ response.description = '@nativescript-community/https > Invalid SSL certificate! ' + response.description;
}
- sendi.content = content;
+ sendi.content = parsedData;
+ sendi.response = response;
resolve(sendi);
}
@@ -294,11 +319,30 @@ function bodyToNative(cont) {
}
return dict;
}
-const configuration = NSURLSessionConfiguration.defaultSessionConfiguration;
-const manager = AFHTTPSessionManager.alloc().initWithSessionConfiguration(configuration);
-export function createRequest(opts: Https.HttpsRequestOptions): Https.HttpsRequest {
- const type = opts.headers && opts.headers['Content-Type'] ? (opts.headers['Content-Type'] as string) : 'application/json';
+const runningRequests: { [k: string]: NSURLSessionDataTask } = {};
+
+export function cancelRequest(tag: string) {
+ if (runningRequests[tag]) {
+ runningRequests[tag].cancel();
+ }
+}
+
+export function cancelAllRequests() {
+ Object.values(runningRequests).forEach((request) => {
+ request.cancel();
+ });
+}
+
+export function clearCookies() {
+ const storage = NSHTTPCookieStorage.sharedHTTPCookieStorage;
+ const cookies = storage.cookies;
+ cookies.enumerateObjectsUsingBlock((cookie) => {
+ storage.deleteCookie(cookie);
+ });
+}
+export function createRequest(opts: HttpsRequestOptions, useLegacy: boolean = true): HttpsRequest {
+ const type = opts.headers && opts.headers['Content-Type'] ? opts.headers['Content-Type'] : 'application/json';
if (type.startsWith('application/json')) {
manager.requestSerializer = AFJSONRequestSerializer.serializer();
manager.responseSerializer = AFJSONResponseSerializer.serializerWithReadingOptions(NSJSONReadingOptions.AllowFragments);
@@ -307,7 +351,7 @@ export function createRequest(opts: Https.HttpsRequestOptions): Https.HttpsReque
manager.responseSerializer = AFHTTPResponseSerializer.serializer();
}
manager.requestSerializer.allowsCellularAccess = true;
- manager.requestSerializer.HTTPShouldHandleCookies = true;
+ manager.requestSerializer.HTTPShouldHandleCookies = opts.cookiesEnabled !== false;
manager.securityPolicy = policies.secured === true ? policies.secure : policies.def;
if (opts.cachePolicy) {
@@ -330,7 +374,11 @@ export function createRequest(opts: Https.HttpsRequestOptions): Https.HttpsReque
if (heads) {
headers = NSMutableDictionary.dictionary();
Object.keys(heads).forEach(
- (key) => headers.setValueForKey(heads[key], key)
+ (key) => {
+ if (heads[key]) {
+ headers.setValueForKey(heads[key], key);
+ }
+ }
// manager.requestSerializer.setValueForHTTPHeaderField(
// heads[key] as any,
// key
@@ -338,24 +386,27 @@ export function createRequest(opts: Https.HttpsRequestOptions): Https.HttpsReque
);
}
- let dict = null;
- if (opts.body) {
- dict = bodyToNative(opts.body);
- } else if (opts.content) {
- dict = opts.content;
- }
-
manager.requestSerializer.timeoutInterval = opts.timeout ? opts.timeout : 10;
- const useLegacy = Utils.isDefined(opts.useLegacy) ? opts.useLegacy : false;
-
const progress = opts.onProgress
? (progress: NSProgress) => {
- opts.onProgress(progress.completedUnitCount, progress.totalUnitCount);
+ if (opts.progressOnMainThread === false || (opts.progressOnMainThread === undefined && opts.responseOnMainThread === false)) {
+ opts.onProgress(progress.completedUnitCount, progress.totalUnitCount);
+ } else {
+ Utils.dispatchToMainThread(() => {
+ opts.onProgress(progress.completedUnitCount, progress.totalUnitCount);
+ });
+ }
}
: null;
let task: NSURLSessionDataTask;
+ const tag = opts.tag;
+ function clearRunningRequest() {
+ if (tag) {
+ delete runningRequests[tag];
+ }
+ }
return {
get nativeRequest() {
return task;
@@ -363,15 +414,18 @@ export function createRequest(opts: Https.HttpsRequestOptions): Https.HttpsReque
cancel: () => task && task.cancel(),
run(resolve, reject) {
const success = function (task: NSURLSessionDataTask, data?: any) {
+ clearRunningRequest();
// TODO: refactor this code with failure one.
- const content = useLegacy ? new HttpsResponse(data, opts.url) : getData(data);
+ const contentLength = task.countOfBytesReceived;
+ const content = useLegacy ? new HttpsResponseLegacy(data, contentLength, opts.url) : getData(data);
let getHeaders = () => ({});
- const sendi: Https.HttpsResponse = {
+ const sendi = {
content,
+ contentLength,
get headers() {
return getHeaders();
- },
- };
+ }
+ } as any as HttpsResponse;
const response = task.response as NSHTTPURLResponse;
if (!Utils.isNullOrUndefined(response)) {
@@ -393,6 +447,7 @@ export function createRequest(opts: Https.HttpsRequestOptions): Https.HttpsReque
// }
};
const failure = function (task: NSURLSessionDataTask, error: any) {
+ clearRunningRequest();
AFFailure(resolve, reject, task, error, useLegacy, opts.url);
};
if (type.startsWith('multipart/form-data')) {
@@ -405,13 +460,27 @@ export function createRequest(opts: Https.HttpsRequestOptions): Https.HttpsReque
null,
headers,
(formData) => {
- (opts.body as Https.HttpsFormDataParam[]).forEach((param) => {
+ (opts.body as HttpsFormDataParam[]).forEach((param) => {
if (param.fileName && param.contentType) {
if (param.data instanceof NSURL) {
formData.appendPartWithFileURLNameFileNameMimeTypeError(param.data, param.parameterName, param.fileName, param.contentType);
+ } else if (param.data instanceof File) {
+ formData.appendPartWithFileURLNameFileNameMimeTypeError(NSURL.fileURLWithPath(param.data.path), param.parameterName, param.fileName, param.contentType);
} else {
- // console.log('addding file data', param.data instanceof NSData);
- formData.appendPartWithFileDataNameFileNameMimeType(param.data, param.parameterName, param.fileName, param.contentType);
+ let data = param.data;
+ if (typeof data === 'string') {
+ data = NSString.stringWithString(data).dataUsingEncoding(NSUTF8StringEncoding);
+ } else if (data instanceof ArrayBuffer) {
+ const buffer = new Uint8Array(data);
+ data = NSData.dataWithData(buffer as any);
+ } else if (typeof Blob !== 'undefined' && data instanceof Blob) {
+ // Stolen from core xhr, not sure if we should use InternalAccessor, but it provides fast access.
+ // @ts-ignore
+ const buffer = new Uint8Array(Blob.InternalAccessor.getBuffer(data).buffer.slice(0) as ArrayBuffer);
+ data = NSData.dataWithData(buffer as any);
+ }
+
+ formData.appendPartWithFileDataNameFileNameMimeType(data, param.parameterName, param.fileName, param.contentType);
}
} else {
formData.appendPartWithFormDataName(NSString.stringWithString(param.data).dataUsingEncoding(NSUTF8StringEncoding), param.parameterName);
@@ -426,39 +495,81 @@ export function createRequest(opts: Https.HttpsRequestOptions): Https.HttpsReque
default:
throw new Error('method_not_supported_multipart');
}
+ } else if (opts.method === 'PUT') {
+ if (opts.body instanceof File) {
+ const request = createNSRequest(opts.url);
+ request.HTTPMethod = opts.method;
+ Object.keys(heads).forEach((k) => {
+ request.setValueForHTTPHeaderField(heads[k], k);
+ });
+ task = manager.uploadTaskWithRequestFromFileProgressCompletionHandler(
+ request,
+ NSURL.fileURLWithPath(opts.body.path),
+ progress,
+ (response: NSURLResponse, responseObject: any, error: NSError) => {
+ if (error) {
+ failure(task, error);
+ } else {
+ success(task, responseObject);
+ }
+ }
+ );
+ task.resume();
+ } else {
+ let data: NSData;
+ // TODO: add support for Buffers
+ if (opts.content instanceof NSData) {
+ data = opts.content;
+ } else if (typeof opts.body === 'string') {
+ data = NSString.stringWithString(opts.body).dataUsingEncoding(NSUTF8StringEncoding);
+ } else {
+ data = NSString.stringWithString(JSON.stringify(opts.body)).dataUsingEncoding(NSUTF8StringEncoding);
+ }
+ const request = createNSRequest(opts.url);
+ request.HTTPMethod = opts.method;
+ Object.keys(heads).forEach((k) => {
+ request.setValueForHTTPHeaderField(heads[k], k);
+ });
+ task = manager.uploadTaskWithRequestFromDataProgressCompletionHandler(request, data, progress, (response: NSURLResponse, responseObject: any, error: NSError) => {
+ if (error) {
+ failure(task, error);
+ } else {
+ success(task, responseObject);
+ }
+ });
+ task.resume();
+ }
} else {
- switch (opts.method) {
- case 'GET':
- task = manager.GETParametersHeadersProgressSuccessFailure(opts.url, dict, headers, progress, success, failure);
- break;
- case 'POST':
- task = manager.POSTParametersHeadersProgressSuccessFailure(opts.url, dict, headers, progress, success, failure);
- break;
- case 'PUT':
- task = manager.PUTParametersHeadersSuccessFailure(opts.url, dict, headers, success, failure);
- break;
- case 'DELETE':
- task = manager.DELETEParametersHeadersSuccessFailure(opts.url, dict, headers, success, failure);
- break;
- case 'PATCH':
- task = manager.PATCHParametersHeadersSuccessFailure(opts.url, dict, headers, success, failure);
- break;
- case 'HEAD':
- task = manager.HEADParametersHeadersSuccessFailure(opts.url, dict, headers, success, failure);
- break;
- default:
- throw new Error('method_not_supported_multipart');
+ let dict = null;
+ if (opts.body) {
+ if (typeof opts.body === 'string') {
+ dict = NSJSONSerialization.JSONObjectWithDataOptionsError(NSString.stringWithString(opts.body).dataUsingEncoding(NSUTF8StringEncoding), 0 as any);
+ } else {
+ dict = NSJSONSerialization.JSONObjectWithDataOptionsError(NSString.stringWithString(JSON.stringify(opts.body)).dataUsingEncoding(NSUTF8StringEncoding), 0 as any);
+ }
+ } else if (typeof opts.content === 'string') {
+ dict = NSJSONSerialization.JSONObjectWithDataOptionsError(NSString.stringWithString(opts.content).dataUsingEncoding(NSUTF8StringEncoding), 0 as any);
}
+ task = manager.dataTaskWithHTTPMethodURLStringParametersHeadersUploadProgressDownloadProgressSuccessFailure(opts.method, opts.url, dict, headers, progress, progress, success, failure);
+ task.resume();
}
- },
+ if (task && tag) {
+ runningRequests[tag] = task;
+ }
+ }
};
}
-export function request(opts: Https.HttpsRequestOptions) {
+export function request(opts: HttpsRequestOptions, useLegacy: boolean = true) {
return new Promise((resolve, reject) => {
try {
- createRequest(opts).run(resolve, reject);
+ createRequest(opts, useLegacy).run(resolve, reject);
} catch (error) {
reject(error);
}
});
}
+
+// Android only
+export function getClient(opts: Partial) {
+ return undefined;
+}
diff --git a/src/typings/android.d.ts b/src/https/typings/android.d.ts
similarity index 59%
rename from src/typings/android.d.ts
rename to src/https/typings/android.d.ts
index e4d67ee..1763688 100644
--- a/src/typings/android.d.ts
+++ b/src/https/typings/android.d.ts
@@ -4,12 +4,17 @@ declare namespace com {
export class QuotePreservingCookieJar extends okhttp3.CookieJar {
constructor(manager: java.net.CookieManager);
}
- export class CacheInterceptor implements okhttp3.Interceptor {
- intercept(chain): okhttp3.Response;
+ export class CacheInterceptor {
+ public static INTERCEPTOR: okhttp3.Interceptor;
+ }
+ export class CacheUtils {
+ static removeCachedResponse(url: string, cache: okhttp3.Cache): void;
}
export class OkHttpResponse {
progressCallback: OkHttpResponse.OkHttpResponseProgressCallback;
closeCallback: OkHttpResponse.OkHttpResponseCloseCallback;
+ runOnMainThread: boolean;
+ runProgressOnMainThread: boolean;
constructor(body: okhttp3.ResponseBody);
contentLength(): number;
cancel();
@@ -17,10 +22,24 @@ declare namespace com {
toByteArrayAsync(callback: OkHttpResponse.OkHttpResponseAsyncCallback);
asString();
asStringAsync(callback: OkHttpResponse.OkHttpResponseAsyncCallback);
- toBitmap();
- toBitmapAsync(callback: OkHttpResponse.OkHttpResponseAsyncCallback);
+ toImage();
+ toImageAsync(callback: OkHttpResponse.OkHttpResponseAsyncCallback);
toFile();
toFileAsync(filePath: string, callback: OkHttpResponse.OkHttpResponseAsyncCallback);
+
+ static getBody(response: okhttp3.Response): okhttp3.ResponseBody;
+ static getStatusCode(response: okhttp3.Response): number;
+ static getMessage(response: okhttp3.Response): string;
+ static getHeaders(response: okhttp3.Response): string;
+ }
+ export class ProgressRequestWrapper extends okhttp3.RequestBody {
+ constructor(body: okhttp3.RequestBody, listener: ProgressRequestWrapper.ProgressListener);
+ }
+ export namespace ProgressRequestWrapper {
+ export class ProgressListener {
+ constructor(impl: { onRequestProgress(current: number, total: number) });
+ onRequestProgress(current: number, total: number);
+ }
}
export namespace OkHttpResponse {
export class OkHttpResponseProgressCallback {
diff --git a/src/typings/objc!AFNetworking.d.ts b/src/https/typings/objc!AFNetworking.d.ts
similarity index 100%
rename from src/typings/objc!AFNetworking.d.ts
rename to src/https/typings/objc!AFNetworking.d.ts
diff --git a/src/https/typings/okhttp3.d.ts b/src/https/typings/okhttp3.d.ts
new file mode 100644
index 0000000..7481e06
--- /dev/null
+++ b/src/https/typings/okhttp3.d.ts
@@ -0,0 +1,4438 @@
+///
+
+declare module okhttp3 {
+ export class Address extends java.lang.Object {
+ public static class: java.lang.Class;
+ /** @deprecated */
+ public proxyAuthenticator(): okhttp3.Authenticator;
+ /** @deprecated */
+ public proxy(): java.net.Proxy;
+ public proxy(): java.net.Proxy;
+ public equals(param0: any): boolean;
+ public sslSocketFactory(): javax.net.ssl.SSLSocketFactory;
+ public equalsNonHost$okhttp(param0: okhttp3.Address): boolean;
+ public certificatePinner(): okhttp3.CertificatePinner;
+ /** @deprecated */
+ public proxySelector(): java.net.ProxySelector;
+ /** @deprecated */
+ public protocols(): java.util.List;
+ public protocols(): java.util.List;
+ public dns(): okhttp3.Dns;
+ public proxyAuthenticator(): okhttp3.Authenticator;
+ public hostnameVerifier(): javax.net.ssl.HostnameVerifier;
+ public constructor(param0: string, param1: number, param2: okhttp3.Dns, param3: javax.net.SocketFactory, param4: javax.net.ssl.SSLSocketFactory, param5: javax.net.ssl.HostnameVerifier, param6: okhttp3.CertificatePinner, param7: okhttp3.Authenticator, param8: java.net.Proxy, param9: java.util.List, param10: java.util.List, param11: java.net.ProxySelector);
+ public hashCode(): number;
+ public connectionSpecs(): java.util.List;
+ /** @deprecated */
+ public sslSocketFactory(): javax.net.ssl.SSLSocketFactory;
+ /** @deprecated */
+ public certificatePinner(): okhttp3.CertificatePinner;
+ /** @deprecated */
+ public url(): okhttp3.HttpUrl;
+ public proxySelector(): java.net.ProxySelector;
+ public url(): okhttp3.HttpUrl;
+ public toString(): string;
+ /** @deprecated */
+ public connectionSpecs(): java.util.List;
+ /** @deprecated */
+ public dns(): okhttp3.Dns;
+ public socketFactory(): javax.net.SocketFactory;
+ /** @deprecated */
+ public hostnameVerifier(): javax.net.ssl.HostnameVerifier;
+ /** @deprecated */
+ public socketFactory(): javax.net.SocketFactory;
+ }
+}
+
+declare module okhttp3 {
+ export class Authenticator extends java.lang.Object {
+ public static class: java.lang.Class;
+ /**
+ * Constructs a new instance of the okhttp3.Authenticator interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ authenticate(param0: okhttp3.Route, param1: okhttp3.Response): okhttp3.Request;
+ (): void;
+ });
+ public constructor();
+ public static NONE: okhttp3.Authenticator;
+ public static JAVA_NET_AUTHENTICATOR: okhttp3.Authenticator;
+ public authenticate(param0: okhttp3.Route, param1: okhttp3.Response): okhttp3.Request;
+ }
+ export module Authenticator {
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ }
+ export module Companion {
+ export class AuthenticatorNone extends java.lang.Object implements okhttp3.Authenticator {
+ public static class: java.lang.Class;
+ public authenticate(param0: okhttp3.Route, param1: okhttp3.Response): okhttp3.Request;
+ public constructor();
+ }
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class Cache extends java.lang.Object implements java.io.Closeable, java.io.Flushable {
+ public static class: java.lang.Class;
+ public trackConditionalCacheHit$okhttp(): void;
+ public close(): void;
+ public directory(): java.io.File;
+ public constructor(param0: java.io.File, param1: number);
+ public writeAbortCount(): number;
+ public constructor(param0: java.io.File, param1: number, param2: okhttp3.internal.io.FileSystem);
+ /** @deprecated */
+ public directory(): java.io.File;
+ public isClosed(): boolean;
+ public delete(): void;
+ public put$okhttp(param0: okhttp3.Response): okhttp3.internal.cache.CacheRequest;
+ public size(): number;
+ public update$okhttp(param0: okhttp3.Response, param1: okhttp3.Response): void;
+ public trackResponse$okhttp(param0: okhttp3.internal.cache.CacheStrategy): void;
+ public urls(): java.util.Iterator;
+ public maxSize(): number;
+ public getWriteSuccessCount$okhttp(): number;
+ public getCache$okhttp(): okhttp3.internal.cache.DiskLruCache;
+ public get$okhttp(param0: okhttp3.Request): okhttp3.Response;
+ public static key(param0: okhttp3.HttpUrl): string;
+ public setWriteAbortCount$okhttp(param0: number): void;
+ public setWriteSuccessCount$okhttp(param0: number): void;
+ public evictAll(): void;
+ public networkCount(): number;
+ public getWriteAbortCount$okhttp(): number;
+ public requestCount(): number;
+ public flush(): void;
+ public remove$okhttp(param0: okhttp3.Request): void;
+ public initialize(): void;
+ public writeSuccessCount(): number;
+ public hitCount(): number;
+ }
+ export module Cache {
+ export class CacheResponseBody extends okhttp3.ResponseBody {
+ public static class: java.lang.Class;
+ public getSnapshot(): okhttp3.internal.cache.DiskLruCache.Snapshot;
+ public contentLength(): number;
+ public source(): okio.BufferedSource;
+ public contentType(): okhttp3.MediaType;
+ public constructor();
+ public close(): void;
+ public constructor(param0: okhttp3.internal.cache.DiskLruCache.Snapshot, param1: string, param2: string);
+ }
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public varyMatches(param0: okhttp3.Response, param1: okhttp3.Headers, param2: okhttp3.Request): boolean;
+ public readInt$okhttp(param0: okio.BufferedSource): number;
+ public varyHeaders(param0: okhttp3.Response): okhttp3.Headers;
+ public key(param0: okhttp3.HttpUrl): string;
+ public hasVaryAll(param0: okhttp3.Response): boolean;
+ }
+ export class Entry extends java.lang.Object {
+ public static class: java.lang.Class;
+ public matches(param0: okhttp3.Request, param1: okhttp3.Response): boolean;
+ public constructor(param0: okhttp3.Response);
+ public constructor(param0: okio.Source);
+ public response(param0: okhttp3.internal.cache.DiskLruCache.Snapshot): okhttp3.Response;
+ public writeTo(param0: okhttp3.internal.cache.DiskLruCache.Editor): void;
+ }
+ export module Entry {
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ }
+ }
+ export class RealCacheRequest extends java.lang.Object implements okhttp3.internal.cache.CacheRequest {
+ public static class: java.lang.Class;
+ public getDone(): boolean;
+ public body(): okio.Sink;
+ public setDone(param0: boolean): void;
+ public abort(): void;
+ public constructor(param0: okhttp3.internal.cache.DiskLruCache.Editor);
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class CacheControl extends java.lang.Object {
+ public static class: java.lang.Class;
+ public static FORCE_NETWORK: okhttp3.CacheControl;
+ public static FORCE_CACHE: okhttp3.CacheControl;
+ /** @deprecated */
+ public mustRevalidate(): boolean;
+ public maxStaleSeconds(): number;
+ public mustRevalidate(): boolean;
+ public toString(): string;
+ public static parse(param0: okhttp3.Headers): okhttp3.CacheControl;
+ /** @deprecated */
+ public maxAgeSeconds(): number;
+ /** @deprecated */
+ public sMaxAgeSeconds(): number;
+ /** @deprecated */
+ public noTransform(): boolean;
+ public minFreshSeconds(): number;
+ public onlyIfCached(): boolean;
+ /** @deprecated */
+ public noStore(): boolean;
+ public noCache(): boolean;
+ public noTransform(): boolean;
+ /** @deprecated */
+ public minFreshSeconds(): number;
+ /** @deprecated */
+ public onlyIfCached(): boolean;
+ public isPrivate(): boolean;
+ public immutable(): boolean;
+ /** @deprecated */
+ public noCache(): boolean;
+ public sMaxAgeSeconds(): number;
+ /** @deprecated */
+ public immutable(): boolean;
+ /** @deprecated */
+ public maxStaleSeconds(): number;
+ public noStore(): boolean;
+ public maxAgeSeconds(): number;
+ public isPublic(): boolean;
+ }
+ export module CacheControl {
+ export class Builder extends java.lang.Object {
+ public static class: java.lang.Class;
+ public noCache(): okhttp3.CacheControl.Builder;
+ public maxStale(param0: number, param1: java.util.concurrent.TimeUnit): okhttp3.CacheControl.Builder;
+ public immutable(): okhttp3.CacheControl.Builder;
+ public onlyIfCached(): okhttp3.CacheControl.Builder;
+ public minFresh(param0: number, param1: java.util.concurrent.TimeUnit): okhttp3.CacheControl.Builder;
+ public maxAge(param0: number, param1: java.util.concurrent.TimeUnit): okhttp3.CacheControl.Builder;
+ public constructor();
+ public build(): okhttp3.CacheControl;
+ public noStore(): okhttp3.CacheControl.Builder;
+ public noTransform(): okhttp3.CacheControl.Builder;
+ }
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public parse(param0: okhttp3.Headers): okhttp3.CacheControl;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class Call extends java.lang.Object implements java.lang.Cloneable {
+ public static class: java.lang.Class;
+ /**
+ * Constructs a new instance of the okhttp3.Call interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ request(): okhttp3.Request;
+ execute(): okhttp3.Response;
+ enqueue(param0: okhttp3.Callback): void;
+ cancel(): void;
+ isExecuted(): boolean;
+ isCanceled(): boolean;
+ timeout(): okio.Timeout;
+ clone(): okhttp3.Call;
+ });
+ public constructor();
+ public isExecuted(): boolean;
+ public clone(): okhttp3.Call;
+ public request(): okhttp3.Request;
+ public execute(): okhttp3.Response;
+ public isCanceled(): boolean;
+ public clone(): any;
+ public enqueue(param0: okhttp3.Callback): void;
+ public cancel(): void;
+ public timeout(): okio.Timeout;
+ }
+ export module Call {
+ export class Factory extends java.lang.Object {
+ public static class: java.lang.Class;
+ /**
+ * Constructs a new instance of the okhttp3.Call$Factory interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ newCall(param0: okhttp3.Request): okhttp3.Call;
+ });
+ public constructor();
+ public newCall(param0: okhttp3.Request): okhttp3.Call;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class Callback extends java.lang.Object {
+ public static class: java.lang.Class;
+ /**
+ * Constructs a new instance of the okhttp3.Callback interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ onFailure(param0: okhttp3.Call, param1: java.io.IOException): void;
+ onResponse(param0: okhttp3.Call, param1: okhttp3.Response): void;
+ });
+ public constructor();
+ public onResponse(param0: okhttp3.Call, param1: okhttp3.Response): void;
+ public onFailure(param0: okhttp3.Call, param1: java.io.IOException): void;
+ }
+}
+
+declare module okhttp3 {
+ export class CertificatePinner extends java.lang.Object {
+ public static class: java.lang.Class;
+ public static DEFAULT: okhttp3.CertificatePinner;
+ public equals(param0: any): boolean;
+ /** @deprecated */
+ public check(param0: string, param1: androidNative.Array): void;
+ public static sha256Hash(param0: java.security.cert.X509Certificate): okio.ByteString;
+ public check$okhttp(param0: string, param1: any): void;
+ public getCertificateChainCleaner$okhttp(): okhttp3.internal.tls.CertificateChainCleaner;
+ public static sha1Hash(param0: java.security.cert.X509Certificate): okio.ByteString;
+ public withCertificateChainCleaner$okhttp(param0: okhttp3.internal.tls.CertificateChainCleaner): okhttp3.CertificatePinner;
+ public static pin(param0: java.security.cert.Certificate): string;
+ public findMatchingPins(param0: string): java.util.List;
+ public hashCode(): number;
+ public constructor(param0: java.util.Set, param1: okhttp3.internal.tls.CertificateChainCleaner);
+ public check(param0: string, param1: java.util.List): void;
+ public getPins(): java.util.Set;
+ }
+ export module CertificatePinner {
+ export class Builder extends java.lang.Object {
+ public static class: java.lang.Class;
+ public build(): okhttp3.CertificatePinner;
+ public constructor();
+ public getPins(): java.util.List;
+ public add(param0: string, param1: androidNative.Array): okhttp3.CertificatePinner.Builder;
+ }
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public sha1Hash(param0: java.security.cert.X509Certificate): okio.ByteString;
+ public sha256Hash(param0: java.security.cert.X509Certificate): okio.ByteString;
+ public pin(param0: java.security.cert.Certificate): string;
+ }
+ export class Pin extends java.lang.Object {
+ public static class: java.lang.Class;
+ public constructor(param0: string, param1: string);
+ public matchesHostname(param0: string): boolean;
+ public equals(param0: any): boolean;
+ public toString(): string;
+ public matchesCertificate(param0: java.security.cert.X509Certificate): boolean;
+ public getHash(): okio.ByteString;
+ public getHashAlgorithm(): string;
+ public getPattern(): string;
+ public hashCode(): number;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class Challenge extends java.lang.Object {
+ public static class: java.lang.Class;
+ public equals(param0: any): boolean;
+ public scheme(): string;
+ /** @deprecated */
+ public scheme(): string;
+ public toString(): string;
+ public constructor(param0: string, param1: java.util.Map);
+ public withCharset(param0: java.nio.charset.Charset): okhttp3.Challenge;
+ public realm(): string;
+ public constructor(param0: string, param1: string);
+ public authParams(): java.util.Map;
+ public charset(): java.nio.charset.Charset;
+ /** @deprecated */
+ public charset(): java.nio.charset.Charset;
+ /** @deprecated */
+ public authParams(): java.util.Map;
+ public hashCode(): number;
+ /** @deprecated */
+ public realm(): string;
+ }
+}
+
+declare module okhttp3 {
+ export class CipherSuite extends java.lang.Object {
+ public static class: java.lang.Class;
+ public static TLS_RSA_WITH_NULL_MD5: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_NULL_SHA: okhttp3.CipherSuite;
+ public static TLS_RSA_EXPORT_WITH_RC4_40_MD5: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_RC4_128_MD5: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_RC4_128_SHA: okhttp3.CipherSuite;
+ public static TLS_RSA_EXPORT_WITH_DES40_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_DES_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_3DES_EDE_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_DSS_WITH_DES_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_WITH_DES_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DH_anon_EXPORT_WITH_RC4_40_MD5: okhttp3.CipherSuite;
+ public static TLS_DH_anon_WITH_RC4_128_MD5: okhttp3.CipherSuite;
+ public static TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DH_anon_WITH_DES_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_KRB5_WITH_DES_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_KRB5_WITH_3DES_EDE_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_KRB5_WITH_RC4_128_SHA: okhttp3.CipherSuite;
+ public static TLS_KRB5_WITH_DES_CBC_MD5: okhttp3.CipherSuite;
+ public static TLS_KRB5_WITH_3DES_EDE_CBC_MD5: okhttp3.CipherSuite;
+ public static TLS_KRB5_WITH_RC4_128_MD5: okhttp3.CipherSuite;
+ public static TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA: okhttp3.CipherSuite;
+ public static TLS_KRB5_EXPORT_WITH_RC4_40_SHA: okhttp3.CipherSuite;
+ public static TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5: okhttp3.CipherSuite;
+ public static TLS_KRB5_EXPORT_WITH_RC4_40_MD5: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_AES_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_DSS_WITH_AES_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_WITH_AES_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DH_anon_WITH_AES_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_AES_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_DSS_WITH_AES_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_WITH_AES_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DH_anon_WITH_AES_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_NULL_SHA256: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_AES_128_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_AES_256_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_DH_anon_WITH_AES_128_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_DH_anon_WITH_AES_256_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_PSK_WITH_RC4_128_SHA: okhttp3.CipherSuite;
+ public static TLS_PSK_WITH_3DES_EDE_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_PSK_WITH_AES_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_PSK_WITH_AES_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_SEED_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_AES_128_GCM_SHA256: okhttp3.CipherSuite;
+ public static TLS_RSA_WITH_AES_256_GCM_SHA384: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: okhttp3.CipherSuite;
+ public static TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: okhttp3.CipherSuite;
+ public static TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: okhttp3.CipherSuite;
+ public static TLS_DH_anon_WITH_AES_128_GCM_SHA256: okhttp3.CipherSuite;
+ public static TLS_DH_anon_WITH_AES_256_GCM_SHA384: okhttp3.CipherSuite;
+ public static TLS_EMPTY_RENEGOTIATION_INFO_SCSV: okhttp3.CipherSuite;
+ public static TLS_FALLBACK_SCSV: okhttp3.CipherSuite;
+ public static TLS_ECDH_ECDSA_WITH_NULL_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_ECDSA_WITH_RC4_128_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_ECDSA_WITH_NULL_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_RSA_WITH_NULL_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_RSA_WITH_RC4_128_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_RSA_WITH_NULL_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_RSA_WITH_RC4_128_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_anon_WITH_NULL_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_anon_WITH_RC4_128_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_anon_WITH_AES_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDH_anon_WITH_AES_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: okhttp3.CipherSuite;
+ public static TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: okhttp3.CipherSuite;
+ public static TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: okhttp3.CipherSuite;
+ public static TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: okhttp3.CipherSuite;
+ public static TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: okhttp3.CipherSuite;
+ public static TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: okhttp3.CipherSuite;
+ public static TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: okhttp3.CipherSuite;
+ public static TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: okhttp3.CipherSuite;
+ public static TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: okhttp3.CipherSuite;
+ public static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: okhttp3.CipherSuite;
+ public static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: okhttp3.CipherSuite;
+ public static TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: okhttp3.CipherSuite;
+ public static TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: okhttp3.CipherSuite;
+ public static TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: okhttp3.CipherSuite;
+ public static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: okhttp3.CipherSuite;
+ public static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: okhttp3.CipherSuite;
+ public static TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: okhttp3.CipherSuite;
+ public static TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: okhttp3.CipherSuite;
+ public static TLS_AES_128_GCM_SHA256: okhttp3.CipherSuite;
+ public static TLS_AES_256_GCM_SHA384: okhttp3.CipherSuite;
+ public static TLS_CHACHA20_POLY1305_SHA256: okhttp3.CipherSuite;
+ public static TLS_AES_128_CCM_SHA256: okhttp3.CipherSuite;
+ public static TLS_AES_128_CCM_8_SHA256: okhttp3.CipherSuite;
+ public javaName(): string;
+ public static forJavaName(param0: string): okhttp3.CipherSuite;
+ /** @deprecated */
+ public javaName(): string;
+ public toString(): string;
+ }
+ export module CipherSuite {
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public forJavaName(param0: string): okhttp3.CipherSuite;
+ public getORDER_BY_NAME$okhttp(): java.util.Comparator;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class Connection extends java.lang.Object {
+ public static class: java.lang.Class;
+ /**
+ * Constructs a new instance of the okhttp3.Connection interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ route(): okhttp3.Route;
+ socket(): java.net.Socket;
+ handshake(): okhttp3.Handshake;
+ protocol(): okhttp3.Protocol;
+ });
+ public constructor();
+ public route(): okhttp3.Route;
+ public protocol(): okhttp3.Protocol;
+ public handshake(): okhttp3.Handshake;
+ public socket(): java.net.Socket;
+ }
+}
+
+declare module okhttp3 {
+ export class ConnectionPool extends java.lang.Object {
+ public static class: java.lang.Class;
+ public constructor();
+ public connectionCount(): number;
+ public getDelegate$okhttp(): okhttp3.internal.connection.RealConnectionPool;
+ public evictAll(): void;
+ public idleConnectionCount(): number;
+ public constructor(param0: okhttp3.internal.connection.RealConnectionPool);
+ public constructor(param0: number, param1: number, param2: java.util.concurrent.TimeUnit);
+ }
+}
+
+declare module okhttp3 {
+ export class ConnectionSpec extends java.lang.Object {
+ public static class: java.lang.Class;
+ public static RESTRICTED_TLS: okhttp3.ConnectionSpec;
+ public static MODERN_TLS: okhttp3.ConnectionSpec;
+ public static COMPATIBLE_TLS: okhttp3.ConnectionSpec;
+ public static CLEARTEXT: okhttp3.ConnectionSpec;
+ /** @deprecated */
+ public supportsTlsExtensions(): boolean;
+ public cipherSuites(): java.util.List;
+ public equals(param0: any): boolean;
+ public supportsTlsExtensions(): boolean;
+ public tlsVersions(): java.util.List;
+ public toString(): string;
+ /** @deprecated */
+ public cipherSuites(): java.util.List;
+ public hashCode(): number;
+ public isCompatible(param0: javax.net.ssl.SSLSocket): boolean;
+ public isTls(): boolean;
+ public apply$okhttp(param0: javax.net.ssl.SSLSocket, param1: boolean): void;
+ /** @deprecated */
+ public tlsVersions(): java.util.List;
+ public constructor(param0: boolean, param1: boolean, param2: androidNative.Array, param3: androidNative.Array);
+ }
+ export module ConnectionSpec {
+ export class Builder extends java.lang.Object {
+ public static class: java.lang.Class;
+ public getCipherSuites$okhttp(): androidNative.Array;
+ public build(): okhttp3.ConnectionSpec;
+ public constructor(param0: boolean);
+ public tlsVersions(param0: androidNative.Array): okhttp3.ConnectionSpec.Builder;
+ public getSupportsTlsExtensions$okhttp(): boolean;
+ public constructor(param0: okhttp3.ConnectionSpec);
+ public cipherSuites(param0: androidNative.Array): okhttp3.ConnectionSpec.Builder;
+ public setSupportsTlsExtensions$okhttp(param0: boolean): void;
+ public setTlsVersions$okhttp(param0: androidNative.Array): void;
+ /** @deprecated */
+ public supportsTlsExtensions(param0: boolean): okhttp3.ConnectionSpec.Builder;
+ public getTls$okhttp(): boolean;
+ public setTls$okhttp(param0: boolean): void;
+ public getTlsVersions$okhttp(): androidNative.Array;
+ public cipherSuites(param0: androidNative.Array): okhttp3.ConnectionSpec.Builder;
+ public allEnabledCipherSuites(): okhttp3.ConnectionSpec.Builder;
+ public allEnabledTlsVersions(): okhttp3.ConnectionSpec.Builder;
+ public setCipherSuites$okhttp(param0: androidNative.Array): void;
+ public tlsVersions(param0: androidNative.Array): okhttp3.ConnectionSpec.Builder;
+ }
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class Cookie extends java.lang.Object {
+ public static class: java.lang.Class;
+ public equals(param0: any): boolean;
+ public matches(param0: okhttp3.HttpUrl): boolean;
+ /** @deprecated */
+ public hostOnly(): boolean;
+ /** @deprecated */
+ public expiresAt(): number;
+ public httpOnly(): boolean;
+ /** @deprecated */
+ public path(): string;
+ public expiresAt(): number;
+ /** @deprecated */
+ public name(): string;
+ public toString$okhttp(param0: boolean): string;
+ public hashCode(): number;
+ /** @deprecated */
+ public persistent(): boolean;
+ public secure(): boolean;
+ /** @deprecated */
+ public domain(): string;
+ public domain(): string;
+ /** @deprecated */
+ public httpOnly(): boolean;
+ public static parseAll(param0: okhttp3.HttpUrl, param1: okhttp3.Headers): java.util.List;
+ /** @deprecated */
+ public secure(): boolean;
+ public toString(): string;
+ /** @deprecated */
+ public value(): string;
+ public persistent(): boolean;
+ public static parse(param0: okhttp3.HttpUrl, param1: string): okhttp3.Cookie;
+ public hostOnly(): boolean;
+ public name(): string;
+ public path(): string;
+ public value(): string;
+ }
+ export module Cookie {
+ export class Builder extends java.lang.Object {
+ public static class: java.lang.Class;
+ public domain(param0: string): okhttp3.Cookie.Builder;
+ public hostOnlyDomain(param0: string): okhttp3.Cookie.Builder;
+ public value(param0: string): okhttp3.Cookie.Builder;
+ public httpOnly(): okhttp3.Cookie.Builder;
+ public secure(): okhttp3.Cookie.Builder;
+ public expiresAt(param0: number): okhttp3.Cookie.Builder;
+ public build(): okhttp3.Cookie;
+ public name(param0: string): okhttp3.Cookie.Builder;
+ public constructor();
+ public path(param0: string): okhttp3.Cookie.Builder;
+ }
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public parse$okhttp(param0: number, param1: okhttp3.HttpUrl, param2: string): okhttp3.Cookie;
+ public parse(param0: okhttp3.HttpUrl, param1: string): okhttp3.Cookie;
+ public parseAll(param0: okhttp3.HttpUrl, param1: okhttp3.Headers): java.util.List;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class CookieJar extends java.lang.Object {
+ public static class: java.lang.Class;
+ /**
+ * Constructs a new instance of the okhttp3.CookieJar interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ saveFromResponse(param0: okhttp3.HttpUrl, param1: java.util.List): void;
+ loadForRequest(param0: okhttp3.HttpUrl): java.util.List;
+ (): void;
+ });
+ public constructor();
+ public static NO_COOKIES: okhttp3.CookieJar;
+ public loadForRequest(param0: okhttp3.HttpUrl): java.util.List;
+ public saveFromResponse(param0: okhttp3.HttpUrl, param1: java.util.List): void;
+ }
+ export module CookieJar {
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ }
+ export module Companion {
+ export class NoCookies extends java.lang.Object implements okhttp3.CookieJar {
+ public static class: java.lang.Class;
+ public loadForRequest(param0: okhttp3.HttpUrl): java.util.List;
+ public saveFromResponse(param0: okhttp3.HttpUrl, param1: java.util.List): void;
+ public constructor();
+ }
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class Credentials extends java.lang.Object {
+ public static class: java.lang.Class;
+ public static INSTANCE: okhttp3.Credentials;
+ public static basic(param0: string, param1: string, param2: java.nio.charset.Charset): string;
+ public static basic(param0: string, param1: string): string;
+ }
+}
+
+declare module okhttp3 {
+ export class Dispatcher extends java.lang.Object {
+ public static class: java.lang.Class;
+ public constructor();
+ public setMaxRequestsPerHost(param0: number): void;
+ public constructor(param0: java.util.concurrent.ExecutorService);
+ public queuedCallsCount(): number;
+ /** @deprecated */
+ public executorService(): java.util.concurrent.ExecutorService;
+ public finished$okhttp(param0: okhttp3.internal.connection.RealCall.AsyncCall): void;
+ public runningCallsCount(): number;
+ public runningCalls(): java.util.List;
+ public cancelAll(): void;
+ public queuedCalls(): java.util.List;
+ public setMaxRequests(param0: number): void;
+ public getMaxRequestsPerHost(): number;
+ public executed$okhttp(param0: okhttp3.internal.connection.RealCall): void;
+ public executorService(): java.util.concurrent.ExecutorService;
+ public setIdleCallback(param0: java.lang.Runnable): void;
+ public getIdleCallback(): java.lang.Runnable;
+ public enqueue$okhttp(param0: okhttp3.internal.connection.RealCall.AsyncCall): void;
+ public getMaxRequests(): number;
+ public finished$okhttp(param0: okhttp3.internal.connection.RealCall): void;
+ }
+}
+
+declare module okhttp3 {
+ export class Dns extends java.lang.Object {
+ public static class: java.lang.Class;
+ /**
+ * Constructs a new instance of the okhttp3.Dns interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ lookup(param0: string): java.util.List;
+ (): void;
+ });
+ public constructor();
+ public static SYSTEM: okhttp3.Dns;
+ public lookup(param0: string): java.util.List;
+ }
+ export module Dns {
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ }
+ export module Companion {
+ export class DnsSystem extends java.lang.Object implements okhttp3.Dns {
+ public static class: java.lang.Class;
+ public lookup(param0: string): java.util.List;
+ public constructor();
+ }
+ }
+ }
+}
+
+declare module okhttp3 {
+ export abstract class EventListener extends java.lang.Object {
+ public static class: java.lang.Class;
+ public static NONE: okhttp3.EventListener;
+ public connectFailed(param0: okhttp3.Call, param1: java.net.InetSocketAddress, param2: java.net.Proxy, param3: okhttp3.Protocol, param4: java.io.IOException): void;
+ public proxySelectStart(param0: okhttp3.Call, param1: okhttp3.HttpUrl): void;
+ public proxySelectEnd(param0: okhttp3.Call, param1: okhttp3.HttpUrl, param2: java.util.List): void;
+ public connectionReleased(param0: okhttp3.Call, param1: okhttp3.Connection): void;
+ public dnsEnd(param0: okhttp3.Call, param1: string, param2: java.util.List): void;
+ public secureConnectEnd(param0: okhttp3.Call, param1: okhttp3.Handshake): void;
+ public dnsStart(param0: okhttp3.Call, param1: string): void;
+ public connectEnd(param0: okhttp3.Call, param1: java.net.InetSocketAddress, param2: java.net.Proxy, param3: okhttp3.Protocol): void;
+ public requestHeadersEnd(param0: okhttp3.Call, param1: okhttp3.Request): void;
+ public connectStart(param0: okhttp3.Call, param1: java.net.InetSocketAddress, param2: java.net.Proxy): void;
+ public callFailed(param0: okhttp3.Call, param1: java.io.IOException): void;
+ public constructor();
+ public cacheMiss(param0: okhttp3.Call): void;
+ public callStart(param0: okhttp3.Call): void;
+ public satisfactionFailure(param0: okhttp3.Call, param1: okhttp3.Response): void;
+ public responseBodyEnd(param0: okhttp3.Call, param1: number): void;
+ public responseFailed(param0: okhttp3.Call, param1: java.io.IOException): void;
+ public callEnd(param0: okhttp3.Call): void;
+ public secureConnectStart(param0: okhttp3.Call): void;
+ public responseHeadersEnd(param0: okhttp3.Call, param1: okhttp3.Response): void;
+ public canceled(param0: okhttp3.Call): void;
+ public connectionAcquired(param0: okhttp3.Call, param1: okhttp3.Connection): void;
+ public responseBodyStart(param0: okhttp3.Call): void;
+ public cacheConditionalHit(param0: okhttp3.Call, param1: okhttp3.Response): void;
+ public requestBodyEnd(param0: okhttp3.Call, param1: number): void;
+ public requestFailed(param0: okhttp3.Call, param1: java.io.IOException): void;
+ public requestHeadersStart(param0: okhttp3.Call): void;
+ public requestBodyStart(param0: okhttp3.Call): void;
+ public responseHeadersStart(param0: okhttp3.Call): void;
+ public cacheHit(param0: okhttp3.Call, param1: okhttp3.Response): void;
+ }
+ export module EventListener {
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ }
+ export class Factory extends java.lang.Object {
+ public static class: java.lang.Class;
+ /**
+ * Constructs a new instance of the okhttp3.EventListener$Factory interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ create(param0: okhttp3.Call): okhttp3.EventListener;
+ });
+ public constructor();
+ public create(param0: okhttp3.Call): okhttp3.EventListener;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class FormBody extends okhttp3.RequestBody {
+ public static class: java.lang.Class;
+ public constructor();
+ public value(param0: number): string;
+ public encodedValue(param0: number): string;
+ public name(param0: number): string;
+ public size(): number;
+ public constructor(param0: java.util.List, param1: java.util.List);
+ public encodedName(param0: number): string;
+ public contentType(): okhttp3.MediaType;
+ public writeTo(param0: okio.BufferedSink): void;
+ public contentLength(): number;
+ /** @deprecated */
+ public size(): number;
+ }
+ export module FormBody {
+ export class Builder extends java.lang.Object {
+ public static class: java.lang.Class;
+ public constructor(param0: java.nio.charset.Charset);
+ public addEncoded(param0: string, param1: string): okhttp3.FormBody.Builder;
+ public constructor();
+ public add(param0: string, param1: string): okhttp3.FormBody.Builder;
+ public build(): okhttp3.FormBody;
+ }
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class Handshake extends java.lang.Object {
+ public static class: java.lang.Class;
+ /** @deprecated */
+ public tlsVersion(): okhttp3.TlsVersion;
+ public equals(param0: any): boolean;
+ public localCertificates(): java.util.List;
+ public peerCertificates(): java.util.List;
+ public toString(): string;
+ public peerPrincipal(): java.security.Principal;
+ public static get(param0: okhttp3.TlsVersion, param1: okhttp3.CipherSuite, param2: java.util.List, param3: java.util.List): okhttp3.Handshake;
+ /** @deprecated */
+ public cipherSuite(): okhttp3.CipherSuite;
+ public static get(param0: javax.net.ssl.SSLSession): okhttp3.Handshake;
+ public constructor(param0: okhttp3.TlsVersion, param1: okhttp3.CipherSuite, param2: java.util.List, param3: any);
+ /** @deprecated */
+ public peerPrincipal(): java.security.Principal;
+ /** @deprecated */
+ public localPrincipal(): java.security.Principal;
+ public hashCode(): number;
+ /** @deprecated */
+ public localCertificates(): java.util.List;
+ public localPrincipal(): java.security.Principal;
+ public tlsVersion(): okhttp3.TlsVersion;
+ /** @deprecated */
+ public peerCertificates(): java.util.List;
+ public cipherSuite(): okhttp3.CipherSuite;
+ }
+ export module Handshake {
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public get(param0: javax.net.ssl.SSLSession): okhttp3.Handshake;
+ public get(param0: okhttp3.TlsVersion, param1: okhttp3.CipherSuite, param2: java.util.List, param3: java.util.List): okhttp3.Handshake;
+ /** @deprecated */
+ public get(param0: javax.net.ssl.SSLSession): okhttp3.Handshake;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class Headers extends java.lang.Object {
+ public static class: java.lang.Class;
+ public value(param0: number): string;
+ public equals(param0: any): boolean;
+ public newBuilder(): okhttp3.Headers.Builder;
+ public forEach(param0: any /* any*/): void;
+ public getInstant(param0: string): java.time.Instant;
+ public iterator(): java.util.Iterator;
+ public toString(): string;
+ public get(param0: string): string;
+ public values(param0: string): java.util.List;
+ public names(): java.util.Set;
+ public name(param0: number): string;
+ public size(): number;
+ public iterator(): java.util.Iterator;
+ public spliterator(): java.util.Spliterator;
+ public hashCode(): number;
+ public toMultimap(): java.util.Map>;
+ public getDate(param0: string): java.util.Date;
+ public byteCount(): number;
+ /** @deprecated */
+ public size(): number;
+ }
+ export module Headers {
+ export class Builder extends java.lang.Object {
+ public static class: java.lang.Class;
+ public get(param0: string): string;
+ public build(): okhttp3.Headers;
+ public set(param0: string, param1: java.time.Instant): okhttp3.Headers.Builder;
+ public getNamesAndValues$okhttp(): java.util.List;
+ public set(param0: string, param1: string): okhttp3.Headers.Builder;
+ public constructor();
+ public addAll(param0: okhttp3.Headers): okhttp3.Headers.Builder;
+ public addLenient$okhttp(param0: string, param1: string): okhttp3.Headers.Builder;
+ public add(param0: string, param1: string): okhttp3.Headers.Builder;
+ public removeAll(param0: string): okhttp3.Headers.Builder;
+ public add(param0: string, param1: java.time.Instant): okhttp3.Headers.Builder;
+ public set(param0: string, param1: java.util.Date): okhttp3.Headers.Builder;
+ public add(param0: string): okhttp3.Headers.Builder;
+ public addUnsafeNonAscii(param0: string, param1: string): okhttp3.Headers.Builder;
+ public addLenient$okhttp(param0: string): okhttp3.Headers.Builder;
+ public add(param0: string, param1: java.util.Date): okhttp3.Headers.Builder;
+ }
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ /** @deprecated */
+ public of(param0: androidNative.Array): okhttp3.Headers;
+ /** @deprecated */
+ public of(param0: java.util.Map): okhttp3.Headers;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class HttpUrl extends java.lang.Object {
+ public static class: java.lang.Class;
+ public static USERNAME_ENCODE_SET: string;
+ public static PASSWORD_ENCODE_SET: string;
+ public static PATH_SEGMENT_ENCODE_SET: string;
+ public static PATH_SEGMENT_ENCODE_SET_URI: string;
+ public static QUERY_ENCODE_SET: string;
+ public static QUERY_COMPONENT_REENCODE_SET: string;
+ public static QUERY_COMPONENT_ENCODE_SET: string;
+ public static QUERY_COMPONENT_ENCODE_SET_URI: string;
+ public static FORM_ENCODE_SET: string;
+ public static FRAGMENT_ENCODE_SET: string;
+ public static FRAGMENT_ENCODE_SET_URI: string;
+ public static get(param0: java.net.URI): okhttp3.HttpUrl;
+ public equals(param0: any): boolean;
+ public topPrivateDomain(): string;
+ public queryParameterName(param0: number): string;
+ /** @deprecated */
+ public queryParameterNames(): java.util.Set;
+ public queryParameterNames(): java.util.Set;
+ /** @deprecated */
+ public port(): number;
+ public encodedPassword(): string;
+ public query(): string;
+ /** @deprecated */
+ public pathSegments(): java.util.List;
+ /** @deprecated */
+ public username(): string;
+ /** @deprecated */
+ public encodedUsername(): string;
+ public static get(param0: string): okhttp3.HttpUrl;
+ public pathSize(): number;
+ public isHttps(): boolean;
+ /** @deprecated */
+ public host(): string;
+ public newBuilder(): okhttp3.HttpUrl.Builder;
+ public port(): number;
+ public encodedFragment(): string;
+ public redact(): string;
+ /** @deprecated */
+ public scheme(): string;
+ public fragment(): string;
+ public toString(): string;
+ public uri(): java.net.URI;
+ /** @deprecated */
+ public encodedQuery(): string;
+ public queryParameterValue(param0: number): string;
+ /** @deprecated */
+ public encodedFragment(): string;
+ public host(): string;
+ public static get(param0: java.net.URL): okhttp3.HttpUrl;
+ /** @deprecated */
+ public password(): string;
+ public url(): java.net.URL;
+ public querySize(): number;
+ public static defaultPort(param0: string): number;
+ public scheme(): string;
+ /** @deprecated */
+ public uri(): java.net.URI;
+ public constructor(param0: string, param1: string, param2: string, param3: string, param4: number, param5: java.util.List, param6: java.util.List, param7: string, param8: string);
+ public queryParameter(param0: string): string;
+ /** @deprecated */
+ public encodedPathSegments(): java.util.List;
+ public password(): string;
+ public hashCode(): number;
+ public resolve(param0: string): okhttp3.HttpUrl;
+ public encodedPathSegments(): java.util.List;
+ public encodedQuery(): string;
+ public encodedPath(): string;
+ /** @deprecated */
+ public pathSize(): number;
+ /** @deprecated */
+ public encodedPath(): string;
+ public encodedUsername(): string;
+ public queryParameterValues(param0: string): java.util.List;
+ /** @deprecated */
+ public fragment(): string;
+ public newBuilder(param0: string): okhttp3.HttpUrl.Builder;
+ /** @deprecated */
+ public query(): string;
+ public pathSegments(): java.util.List;
+ public static parse(param0: string): okhttp3.HttpUrl;
+ /** @deprecated */
+ public url(): java.net.URL;
+ /** @deprecated */
+ public encodedPassword(): string;
+ /** @deprecated */
+ public querySize(): number;
+ public username(): string;
+ }
+ export module HttpUrl {
+ export class Builder extends java.lang.Object {
+ public static class: java.lang.Class;
+ public static INVALID_HOST: string;
+ public addPathSegment(param0: string): okhttp3.HttpUrl.Builder;
+ public addEncodedPathSegment(param0: string): okhttp3.HttpUrl.Builder;
+ public setEncodedQueryParameter(param0: string, param1: string): okhttp3.HttpUrl.Builder;
+ public setQueryParameter(param0: string, param1: string): okhttp3.HttpUrl.Builder;
+ public setEncodedQueryNamesAndValues$okhttp(param0: java.util.List): void;
+ public getEncodedQueryNamesAndValues$okhttp(): java.util.List;
+ public getEncodedPathSegments$okhttp(): java.util.List;
+ public encodedFragment(param0: string): okhttp3.HttpUrl.Builder;
+ public username(param0: string): okhttp3.HttpUrl.Builder;
+ public parse$okhttp(param0: okhttp3.HttpUrl, param1: string): okhttp3.HttpUrl.Builder;
+ public setEncodedFragment$okhttp(param0: string): void;
+ public addPathSegments(param0: string): okhttp3.HttpUrl.Builder;
+ public setPort$okhttp(param0: number): void;
+ public getHost$okhttp(): string;
+ public encodedPath(param0: string): okhttp3.HttpUrl.Builder;
+ public getScheme$okhttp(): string;
+ public setScheme$okhttp(param0: string): void;
+ public encodedPassword(param0: string): okhttp3.HttpUrl.Builder;
+ public addEncodedPathSegments(param0: string): okhttp3.HttpUrl.Builder;
+ public encodedQuery(param0: string): okhttp3.HttpUrl.Builder;
+ public setEncodedUsername$okhttp(param0: string): void;
+ public getPort$okhttp(): number;
+ public host(param0: string): okhttp3.HttpUrl.Builder;
+ public removeAllEncodedQueryParameters(param0: string): okhttp3.HttpUrl.Builder;
+ public setEncodedPathSegment(param0: number, param1: string): okhttp3.HttpUrl.Builder;
+ public setHost$okhttp(param0: string): void;
+ public reencodeForUri$okhttp(): okhttp3.HttpUrl.Builder;
+ public constructor();
+ public encodedUsername(param0: string): okhttp3.HttpUrl.Builder;
+ public password(param0: string): okhttp3.HttpUrl.Builder;
+ public getEncodedUsername$okhttp(): string;
+ public getEncodedPassword$okhttp(): string;
+ public getEncodedFragment$okhttp(): string;
+ public port(param0: number): okhttp3.HttpUrl.Builder;
+ public toString(): string;
+ public addQueryParameter(param0: string, param1: string): okhttp3.HttpUrl.Builder;
+ public addEncodedQueryParameter(param0: string, param1: string): okhttp3.HttpUrl.Builder;
+ public query(param0: string): okhttp3.HttpUrl.Builder;
+ public setPathSegment(param0: number, param1: string): okhttp3.HttpUrl.Builder;
+ public removeAllQueryParameters(param0: string): okhttp3.HttpUrl.Builder;
+ public scheme(param0: string): okhttp3.HttpUrl.Builder;
+ public removePathSegment(param0: number): okhttp3.HttpUrl.Builder;
+ public fragment(param0: string): okhttp3.HttpUrl.Builder;
+ public build(): okhttp3.HttpUrl;
+ public setEncodedPassword$okhttp(param0: string): void;
+ }
+ export module Builder {
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ }
+ }
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public toPathString$okhttp(param0: java.util.List, param1: java.lang.StringBuilder): void;
+ /** @deprecated */
+ public parse(param0: string): okhttp3.HttpUrl;
+ public defaultPort(param0: string): number;
+ public get(param0: java.net.URL): okhttp3.HttpUrl;
+ public get(param0: java.net.URI): okhttp3.HttpUrl;
+ public toQueryNamesAndValues$okhttp(param0: string): java.util.List;
+ /** @deprecated */
+ public get(param0: string): okhttp3.HttpUrl;
+ public percentDecode$okhttp(param0: string, param1: number, param2: number, param3: boolean): string;
+ public canonicalize$okhttp(param0: string, param1: number, param2: number, param3: string, param4: boolean, param5: boolean, param6: boolean, param7: boolean, param8: java.nio.charset.Charset): string;
+ public toQueryString$okhttp(param0: java.util.List, param1: java.lang.StringBuilder): void;
+ public get(param0: string): okhttp3.HttpUrl;
+ public parse(param0: string): okhttp3.HttpUrl;
+ /** @deprecated */
+ public get(param0: java.net.URL): okhttp3.HttpUrl;
+ /** @deprecated */
+ public get(param0: java.net.URI): okhttp3.HttpUrl;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class Interceptor extends java.lang.Object {
+ public static class: java.lang.Class;
+ /**
+ * Constructs a new instance of the okhttp3.Interceptor interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ intercept(param0: okhttp3.Interceptor.Chain): okhttp3.Response;
+ });
+ public constructor();
+ public intercept(param0: okhttp3.Interceptor.Chain): okhttp3.Response;
+ }
+ export module Interceptor {
+ export class Chain extends java.lang.Object {
+ public static class: java.lang.Class;
+ /**
+ * Constructs a new instance of the okhttp3.Interceptor$Chain interface with the provided implementation. An empty constructor exists calling super() when extending the interface class.
+ */
+ public constructor(implementation: {
+ request(): okhttp3.Request;
+ proceed(param0: okhttp3.Request): okhttp3.Response;
+ connection(): okhttp3.Connection;
+ call(): okhttp3.Call;
+ connectTimeoutMillis(): number;
+ withConnectTimeout(param0: number, param1: java.util.concurrent.TimeUnit): okhttp3.Interceptor.Chain;
+ readTimeoutMillis(): number;
+ withReadTimeout(param0: number, param1: java.util.concurrent.TimeUnit): okhttp3.Interceptor.Chain;
+ writeTimeoutMillis(): number;
+ withWriteTimeout(param0: number, param1: java.util.concurrent.TimeUnit): okhttp3.Interceptor.Chain;
+ });
+ public constructor();
+ public request(): okhttp3.Request;
+ public withConnectTimeout(param0: number, param1: java.util.concurrent.TimeUnit): okhttp3.Interceptor.Chain;
+ public call(): okhttp3.Call;
+ public withWriteTimeout(param0: number, param1: java.util.concurrent.TimeUnit): okhttp3.Interceptor.Chain;
+ public readTimeoutMillis(): number;
+ public withReadTimeout(param0: number, param1: java.util.concurrent.TimeUnit): okhttp3.Interceptor.Chain;
+ public proceed(param0: okhttp3.Request): okhttp3.Response;
+ public connection(): okhttp3.Connection;
+ public connectTimeoutMillis(): number;
+ public writeTimeoutMillis(): number;
+ }
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public invoke(param0: any): okhttp3.Interceptor;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class MediaType extends java.lang.Object {
+ public static class: java.lang.Class;
+ public type(): string;
+ public equals(param0: any): boolean;
+ public charset(): java.nio.charset.Charset;
+ public subtype(): string;
+ public parameter(param0: string): string;
+ public charset(param0: java.nio.charset.Charset): java.nio.charset.Charset;
+ public hashCode(): number;
+ public static get(param0: string): okhttp3.MediaType;
+ public static parse(param0: string): okhttp3.MediaType;
+ public toString(): string;
+ /** @deprecated */
+ public type(): string;
+ /** @deprecated */
+ public subtype(): string;
+ }
+ export module MediaType {
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public parse(param0: string): okhttp3.MediaType;
+ public get(param0: string): okhttp3.MediaType;
+ /** @deprecated */
+ public parse(param0: string): okhttp3.MediaType;
+ /** @deprecated */
+ public get(param0: string): okhttp3.MediaType;
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class MultipartBody extends okhttp3.RequestBody {
+ public static class: java.lang.Class;
+ public static MIXED: okhttp3.MediaType;
+ public static ALTERNATIVE: okhttp3.MediaType;
+ public static DIGEST: okhttp3.MediaType;
+ public static PARALLEL: okhttp3.MediaType;
+ public static FORM: okhttp3.MediaType;
+ public constructor();
+ /** @deprecated */
+ public type(): okhttp3.MediaType;
+ public parts(): java.util.List;
+ /** @deprecated */
+ public boundary(): string;
+ public type(): okhttp3.MediaType;
+ public writeTo(param0: okio.BufferedSink): void;
+ public boundary(): string;
+ public size(): number;
+ /** @deprecated */
+ public parts(): java.util.List;
+ public constructor(param0: okio.ByteString, param1: okhttp3.MediaType, param2: java.util.List);
+ public contentType(): okhttp3.MediaType;
+ public part(param0: number): okhttp3.MultipartBody.Part;
+ public contentLength(): number;
+ /** @deprecated */
+ public size(): number;
+ }
+ export module MultipartBody {
+ export class Builder extends java.lang.Object {
+ public static class: java.lang.Class;
+ public setType(param0: okhttp3.MediaType): okhttp3.MultipartBody.Builder;
+ public addPart(param0: okhttp3.MultipartBody.Part): okhttp3.MultipartBody.Builder;
+ public build(): okhttp3.MultipartBody;
+ public addPart(param0: okhttp3.Headers, param1: okhttp3.RequestBody): okhttp3.MultipartBody.Builder;
+ public addPart(param0: okhttp3.RequestBody): okhttp3.MultipartBody.Builder;
+ public addFormDataPart(param0: string, param1: string): okhttp3.MultipartBody.Builder;
+ public addFormDataPart(param0: string, param1: string, param2: okhttp3.RequestBody): okhttp3.MultipartBody.Builder;
+ public constructor();
+ public constructor(param0: string);
+ }
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public appendQuotedString$okhttp(param0: java.lang.StringBuilder, param1: string): void;
+ }
+ export class Part extends java.lang.Object {
+ public static class: java.lang.Class;
+ public headers(): okhttp3.Headers;
+ /** @deprecated */
+ public headers(): okhttp3.Headers;
+ /** @deprecated */
+ public body(): okhttp3.RequestBody;
+ public static create(param0: okhttp3.Headers, param1: okhttp3.RequestBody): okhttp3.MultipartBody.Part;
+ public static createFormData(param0: string, param1: string, param2: okhttp3.RequestBody): okhttp3.MultipartBody.Part;
+ public static create(param0: okhttp3.RequestBody): okhttp3.MultipartBody.Part;
+ public static createFormData(param0: string, param1: string): okhttp3.MultipartBody.Part;
+ public body(): okhttp3.RequestBody;
+ }
+ export module Part {
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public createFormData(param0: string, param1: string): okhttp3.MultipartBody.Part;
+ public createFormData(param0: string, param1: string, param2: okhttp3.RequestBody): okhttp3.MultipartBody.Part;
+ public create(param0: okhttp3.RequestBody): okhttp3.MultipartBody.Part;
+ public create(param0: okhttp3.Headers, param1: okhttp3.RequestBody): okhttp3.MultipartBody.Part;
+ }
+ }
+ }
+}
+
+declare module okhttp3 {
+ export class MultipartReader extends java.lang.Object implements java.io.Closeable {
+ public static class: java.lang.Class;
+ public boundary(): string;
+ public close(): void;
+ public nextPart(): okhttp3.MultipartReader.Part;
+ public constructor(param0: okio.BufferedSource, param1: string);
+ public constructor(param0: okhttp3.ResponseBody);
+ }
+ export module MultipartReader {
+ export class Companion extends java.lang.Object {
+ public static class: java.lang.Class;
+ public getAfterBoundaryOptions(): okio.Options;
+ }
+ export class Part extends java.lang.Object implements java.io.Closeable {
+ public static class: java.lang.Class
Downloads the content from the specified URL as binary and returns an ArrayBuffer.
+