├── .devcontainer └── devcontainer.json ├── .eslintrc.js ├── .github └── workflows │ ├── ci.yml │ ├── publish-npm.yml │ └── release-doctor.yml ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── .release-please-manifest.json ├── .stats.yml ├── .tool-versions ├── Brewfile ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── UPGRADE_8.x.md ├── api.md ├── bin ├── check-release-environment └── publish-npm ├── deno_tests └── api-resources │ └── jwt.test.ts ├── examples ├── .keep └── create-asset.ts ├── jest.config.ts ├── package.json ├── release-please-config.json ├── scripts ├── bootstrap ├── build ├── format ├── lint ├── mock ├── test └── utils │ ├── check-is-in-git-install.sh │ ├── check-version.cjs │ ├── fix-index-exports.cjs │ ├── git-swap.sh │ ├── make-dist-package-json.cjs │ ├── postprocess-files.cjs │ └── upload-artifact.sh ├── src ├── _shims │ ├── MultipartBody.ts │ ├── README.md │ ├── auto │ │ ├── jwt-bun.ts │ │ ├── jwt-deno.ts │ │ ├── jwt-node.ts │ │ ├── jwt.ts │ │ ├── runtime-bun.ts │ │ ├── runtime-deno.ts │ │ ├── runtime-node.ts │ │ ├── runtime.ts │ │ ├── types-deno.ts │ │ ├── types-node.ts │ │ ├── types.d.ts │ │ ├── types.js │ │ └── types.mjs │ ├── bun-runtime.ts │ ├── index-deno.ts │ ├── index.d.ts │ ├── index.js │ ├── index.mjs │ ├── manual-types.d.ts │ ├── manual-types.js │ ├── manual-types.mjs │ ├── node-runtime.ts │ ├── node-types.d.ts │ ├── node-types.js │ ├── node-types.mjs │ ├── registry.ts │ ├── web-runtime.ts │ ├── web-types.d.ts │ ├── web-types.js │ └── web-types.mjs ├── core.ts ├── error.ts ├── index.ts ├── internal │ └── qs │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── formats.ts │ │ ├── index.ts │ │ ├── stringify.ts │ │ ├── types.ts │ │ └── utils.ts ├── lib │ └── .keep ├── pagination.ts ├── resource.ts ├── resources.ts ├── resources │ ├── data.ts │ ├── data │ │ ├── annotations.ts │ │ ├── data.ts │ │ ├── dimensions.ts │ │ ├── errors.ts │ │ ├── exports.ts │ │ ├── filters.ts │ │ ├── incidents.ts │ │ ├── index.ts │ │ ├── metrics.ts │ │ ├── monitoring.ts │ │ ├── monitoring │ │ │ ├── index.ts │ │ │ ├── metrics.ts │ │ │ └── monitoring.ts │ │ ├── real-time.ts │ │ └── video-views.ts │ ├── index.ts │ ├── jwt.ts │ ├── shared.ts │ ├── system.ts │ ├── system │ │ ├── index.ts │ │ ├── signing-keys.ts │ │ └── system.ts │ ├── video.ts │ ├── video │ │ ├── assets.ts │ │ ├── delivery-usage.ts │ │ ├── drm-configurations.ts │ │ ├── index.ts │ │ ├── live-streams.ts │ │ ├── playback-ids.ts │ │ ├── playback-restrictions.ts │ │ ├── transcription-vocabularies.ts │ │ ├── uploads.ts │ │ ├── video.ts │ │ └── web-inputs.ts │ └── webhooks.ts ├── shims │ ├── node.ts │ └── web.ts ├── uploads.ts ├── util │ ├── jwt-types.ts │ └── jwt-util.ts └── version.ts ├── tests ├── api-resources │ ├── data │ │ ├── annotations.test.ts │ │ ├── dimensions.test.ts │ │ ├── errors.test.ts │ │ ├── exports.test.ts │ │ ├── filters.test.ts │ │ ├── incidents.test.ts │ │ ├── metrics.test.ts │ │ ├── monitoring │ │ │ ├── metrics.test.ts │ │ │ └── monitoring.test.ts │ │ ├── real-time.test.ts │ │ └── video-views.test.ts │ ├── jwt.test.ts │ ├── rsaKeys.ts │ ├── rsaPrivateKey.pem │ ├── system │ │ └── signing-keys.test.ts │ ├── video │ │ ├── assets.test.ts │ │ ├── delivery-usage.test.ts │ │ ├── drm-configurations.test.ts │ │ ├── live-streams.test.ts │ │ ├── playback-ids.test.ts │ │ ├── playback-restrictions.test.ts │ │ ├── transcription-vocabularies.test.ts │ │ ├── uploads.test.ts │ │ └── web-inputs.test.ts │ └── webhooks.test.ts ├── form.test.ts ├── index.test.ts ├── qs │ ├── empty-keys-cases.ts │ ├── stringify.test.ts │ └── utils.test.ts ├── responses.test.ts ├── stringifyQuery.test.ts └── uploads.test.ts ├── tsc-multi.json ├── tsconfig.build.json ├── tsconfig.deno.json ├── tsconfig.dist-src.json ├── tsconfig.json └── yarn.lock /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/debian 3 | { 4 | "name": "Development", 5 | "image": "mcr.microsoft.com/devcontainers/typescript-node:latest", 6 | "features": { 7 | "ghcr.io/devcontainers/features/node:1": {} 8 | }, 9 | "postCreateCommand": "yarn install", 10 | "customizations": { 11 | "vscode": { 12 | "extensions": [ 13 | "esbenp.prettier-vscode" 14 | ] 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | plugins: ['@typescript-eslint', 'unused-imports', 'prettier'], 4 | rules: { 5 | 'no-unused-vars': 'off', 6 | 'prettier/prettier': 'error', 7 | 'unused-imports/no-unused-imports': 'error', 8 | }, 9 | root: true, 10 | }; 11 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches-ignore: 5 | - 'generated' 6 | - 'codegen/**' 7 | - 'integrated/**' 8 | - 'stl-preview-head/**' 9 | - 'stl-preview-base/**' 10 | 11 | jobs: 12 | lint: 13 | timeout-minutes: 10 14 | name: lint 15 | runs-on: ${{ github.repository == 'stainless-sdks/mux-node' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} 16 | steps: 17 | - uses: actions/checkout@v4 18 | 19 | - name: Set up Node 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: '18' 23 | 24 | - name: Bootstrap 25 | run: ./scripts/bootstrap 26 | 27 | - name: Check types 28 | run: ./scripts/lint 29 | 30 | build: 31 | timeout-minutes: 5 32 | name: build 33 | runs-on: ${{ github.repository == 'stainless-sdks/mux-node' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} 34 | permissions: 35 | contents: read 36 | id-token: write 37 | steps: 38 | - uses: actions/checkout@v4 39 | 40 | - name: Set up Node 41 | uses: actions/setup-node@v4 42 | with: 43 | node-version: '18' 44 | 45 | - name: Bootstrap 46 | run: ./scripts/bootstrap 47 | 48 | - name: Check build 49 | run: ./scripts/build 50 | 51 | - name: Get GitHub OIDC Token 52 | if: github.repository == 'stainless-sdks/mux-node' 53 | id: github-oidc 54 | uses: actions/github-script@v6 55 | with: 56 | script: core.setOutput('github_token', await core.getIDToken()); 57 | 58 | - name: Upload tarball 59 | if: github.repository == 'stainless-sdks/mux-node' 60 | env: 61 | URL: https://pkg.stainless.com/s 62 | AUTH: ${{ steps.github-oidc.outputs.github_token }} 63 | SHA: ${{ github.sha }} 64 | run: ./scripts/utils/upload-artifact.sh 65 | test: 66 | timeout-minutes: 10 67 | name: test 68 | runs-on: ${{ github.repository == 'stainless-sdks/mux-node' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} 69 | steps: 70 | - uses: actions/checkout@v4 71 | 72 | - name: Set up Node 73 | uses: actions/setup-node@v4 74 | with: 75 | node-version: '20' 76 | 77 | - name: Bootstrap 78 | run: ./scripts/bootstrap 79 | 80 | - name: Run tests 81 | run: ./scripts/test 82 | -------------------------------------------------------------------------------- /.github/workflows/publish-npm.yml: -------------------------------------------------------------------------------- 1 | # This workflow is triggered when a GitHub release is created. 2 | # It can also be run manually to re-publish to NPM in case it failed for some reason. 3 | # You can run this workflow by navigating to https://www.github.com/muxinc/mux-node-sdk/actions/workflows/publish-npm.yml 4 | name: Publish NPM 5 | on: 6 | workflow_dispatch: 7 | 8 | release: 9 | types: [published] 10 | 11 | jobs: 12 | publish: 13 | name: publish 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | 19 | - name: Set up Node 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: '20' 23 | 24 | - name: Install dependencies 25 | run: | 26 | yarn install 27 | 28 | - name: Publish to NPM 29 | run: | 30 | bash ./bin/publish-npm 31 | env: 32 | NPM_TOKEN: ${{ secrets.MUX_NPM_TOKEN || secrets.NPM_TOKEN }} 33 | -------------------------------------------------------------------------------- /.github/workflows/release-doctor.yml: -------------------------------------------------------------------------------- 1 | name: Release Doctor 2 | on: 3 | pull_request: 4 | branches: 5 | - master 6 | workflow_dispatch: 7 | 8 | jobs: 9 | release_doctor: 10 | name: release doctor 11 | runs-on: ubuntu-latest 12 | if: github.repository == 'muxinc/mux-node-sdk' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - name: Check release environment 18 | run: | 19 | bash ./bin/check-release-environment 20 | env: 21 | NPM_TOKEN: ${{ secrets.MUX_NPM_TOKEN || secrets.NPM_TOKEN }} 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .prism.log 2 | node_modules 3 | yarn-error.log 4 | codegen.log 5 | Brewfile.lock.json 6 | dist 7 | dist-deno 8 | /*.tgz 9 | .idea/ 10 | 11 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | CHANGELOG.md 2 | /ecosystem-tests/*/** 3 | /node_modules 4 | /deno 5 | 6 | # don't format tsc output, will break source maps 7 | /dist 8 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "experimentalTernaries": true, 4 | "printWidth": 110, 5 | "singleQuote": true, 6 | "trailingComma": "all" 7 | } 8 | -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "11.1.0" 3 | } 4 | -------------------------------------------------------------------------------- /.stats.yml: -------------------------------------------------------------------------------- 1 | configured_endpoints: 97 2 | openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mux%2Fmux-fe7095c6cd410ecd391f6810083a35d9411a2d9772042eaefed534fd51cd9599.yml 3 | openapi_spec_hash: 104a03331ba4c7f753f583fdb852de11 4 | config_hash: 1ca6806e9f62696760dac4321fce849b 5 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | nodejs 18.17.0 2 | yarn 1.22.22 3 | -------------------------------------------------------------------------------- /Brewfile: -------------------------------------------------------------------------------- 1 | brew "node" 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Setting up the environment 2 | 3 | This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install). 4 | Other package managers may work but are not officially supported for development. 5 | 6 | To set up the repository, run: 7 | 8 | ```sh 9 | $ yarn 10 | $ yarn build 11 | ``` 12 | 13 | This will install all the required dependencies and build output files to `dist/`. 14 | 15 | ## Modifying/Adding code 16 | 17 | Most of the SDK is generated code. Modifications to code will be persisted between generations, but may 18 | result in merge conflicts between manual patches and changes from the generator. The generator will never 19 | modify the contents of the `src/lib/` and `examples/` directories. 20 | 21 | ## Adding and running examples 22 | 23 | All files in the `examples/` directory are not modified by the generator and can be freely edited or added to. 24 | 25 | ```ts 26 | // add an example to examples/.ts 27 | 28 | #!/usr/bin/env -S npm run tsn -T 29 | … 30 | ``` 31 | 32 | ```sh 33 | $ chmod +x examples/.ts 34 | # run the example against your api 35 | $ yarn tsn -T examples/.ts 36 | ``` 37 | 38 | ## Using the repository from source 39 | 40 | If you’d like to use the repository from source, you can either install from git or link to a cloned repository: 41 | 42 | To install via git: 43 | 44 | ```sh 45 | $ npm install git+ssh://git@github.com:muxinc/mux-node-sdk.git 46 | ``` 47 | 48 | Alternatively, to link a local copy of the repo: 49 | 50 | ```sh 51 | # Clone 52 | $ git clone https://www.github.com/muxinc/mux-node-sdk 53 | $ cd mux-node-sdk 54 | 55 | # With yarn 56 | $ yarn link 57 | $ cd ../my-package 58 | $ yarn link @mux/mux-node 59 | 60 | # With pnpm 61 | $ pnpm link --global 62 | $ cd ../my-package 63 | $ pnpm link -—global @mux/mux-node 64 | ``` 65 | 66 | ## Running tests 67 | 68 | Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. 69 | 70 | ```sh 71 | $ npx prism mock path/to/your/openapi.yml 72 | ``` 73 | 74 | ```sh 75 | $ yarn run test 76 | ``` 77 | 78 | ## Linting and formatting 79 | 80 | This repository uses [prettier](https://www.npmjs.com/package/prettier) and 81 | [eslint](https://www.npmjs.com/package/eslint) to format the code in the repository. 82 | 83 | To lint: 84 | 85 | ```sh 86 | $ yarn lint 87 | ``` 88 | 89 | To format and fix all lint issues automatically: 90 | 91 | ```sh 92 | $ yarn fix 93 | ``` 94 | 95 | ## Publishing and releases 96 | 97 | Changes made to this repository via the automated release PR pipeline should publish to npm automatically. If 98 | the changes aren't made through the automated pipeline, you may want to make releases manually. 99 | 100 | ### Publish with a GitHub workflow 101 | 102 | You can release to package managers by using [the `Publish NPM` GitHub action](https://www.github.com/muxinc/mux-node-sdk/actions/workflows/publish-npm.yml). This requires a setup organization or repository secret to be set up. 103 | 104 | ### Publish manually 105 | 106 | If you need to manually release a package, you can run the `bin/publish-npm` script with an `NPM_TOKEN` set on 107 | the environment. 108 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting Security Issues 4 | 5 | This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. 6 | 7 | To report a security issue, please contact the Stainless team at security@stainless.com. 8 | 9 | ## Responsible Disclosure 10 | 11 | We appreciate the efforts of security researchers and individuals who help us maintain the security of 12 | SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible 13 | disclosure practices by allowing us a reasonable amount of time to investigate and address the issue 14 | before making any information public. 15 | 16 | ## Reporting Non-SDK Related Security Issues 17 | 18 | If you encounter security issues that are not directly related to SDKs but pertain to the services 19 | or products provided by Mux please follow the respective company's security reporting guidelines. 20 | 21 | ### Mux Terms and Policies 22 | 23 | Please contact devex@mux.com for any questions or concerns regarding security of our services. 24 | 25 | --- 26 | 27 | Thank you for helping us keep the SDKs and systems they interact with secure. 28 | -------------------------------------------------------------------------------- /UPGRADE_8.x.md: -------------------------------------------------------------------------------- 1 | # Upgrading to 8.x 2 | 3 | If you're coming a version of this SDK before 8.0 then a lot has changed. 4 | 5 | For context & background see the [announcement issue](https://github.com/muxinc/mux-node-sdk/issues/327). 6 | 7 | ## Codemod 8 | 9 | There is a codemod script you can run which will modify the old function calls to the new 8.0 syntax: 10 | 11 | ``` 12 | npx @getgrit/launcher apply mux_v8 13 | ``` 14 | 15 | This will edit the files in your project in a way that converts your existing code to the new v8 syntax. The codemod script is working well for us, but you should still verify your code changes and make sure it works as expected before deploying the new code to production. 16 | 17 | This codemod script was tested and run against code running 7.x versions of the SDK. If you're on a version before 7.x you can still run it, but it might not work as reliably and if you're running into issues you may want to upgrade to 7.3.5 before running the codemod. 18 | 19 | ## Documentation 20 | 21 | The current [README](https://github.com/muxinc/mux-node-sdk/blob/master/README.md) has everything else to get started with version 8. 22 | 23 | You also may want to look at [api.md](https://github.com/muxinc/mux-node-sdk/blob/master/api.md) for a full API reference. 24 | -------------------------------------------------------------------------------- /bin/check-release-environment: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | errors=() 4 | 5 | if [ -z "${NPM_TOKEN}" ]; then 6 | errors+=("The MUX_NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets") 7 | fi 8 | 9 | lenErrors=${#errors[@]} 10 | 11 | if [[ lenErrors -gt 0 ]]; then 12 | echo -e "Found the following errors in the release environment:\n" 13 | 14 | for error in "${errors[@]}"; do 15 | echo -e "- $error\n" 16 | done 17 | 18 | exit 1 19 | fi 20 | 21 | echo "The environment is ready to push releases!" 22 | 23 | -------------------------------------------------------------------------------- /bin/publish-npm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eux 4 | 5 | npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" 6 | 7 | # Build the project 8 | yarn build 9 | 10 | # Navigate to the dist directory 11 | cd dist 12 | 13 | # Get the version from package.json 14 | VERSION="$(node -p "require('./package.json').version")" 15 | 16 | # Extract the pre-release tag if it exists 17 | if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then 18 | # Extract the part before any dot in the pre-release identifier 19 | TAG="${BASH_REMATCH[1]}" 20 | else 21 | TAG="latest" 22 | fi 23 | 24 | # Publish with the appropriate tag 25 | yarn publish --access public --tag "$TAG" 26 | -------------------------------------------------------------------------------- /examples/.keep: -------------------------------------------------------------------------------- 1 | File generated from our OpenAPI spec by Stainless. 2 | 3 | This directory can be used to store example files demonstrating usage of this SDK. 4 | It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. 5 | -------------------------------------------------------------------------------- /examples/create-asset.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S npm run tsn -T 2 | import Mux from '@mux/mux-node'; 3 | 4 | const mux = new Mux({ 5 | // These are dev env values 6 | tokenId: 'b5a8e345-c160-4481-8d83-cf32d0ed1683', 7 | tokenSecret: 'DVCYh4ijEQDob+5ZW6BOweLvyDDpCi+r4T/6dcf+K8YylZduiOAK2eS6vdTfauFXg6rldRKSofe', 8 | }); 9 | 10 | async function main() { 11 | const asset = await mux.video.assets.create({ 12 | inputs: [{ url: 'https://storage.googleapis.com/muxdemofiles/mux-video-intro.mp4' }], 13 | playback_policies: ['public'], 14 | }); 15 | console.log(asset); 16 | 17 | const assets = []; 18 | for await (const asset of mux.video.assets.list()) { 19 | console.log(asset.id); 20 | assets.push(asset); 21 | } 22 | console.log(assets.length); 23 | } 24 | 25 | main().catch((err) => { 26 | console.error(err); 27 | process.exit(1); 28 | }); 29 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import type { JestConfigWithTsJest } from 'ts-jest'; 2 | 3 | const config: JestConfigWithTsJest = { 4 | preset: 'ts-jest/presets/default-esm', 5 | testEnvironment: 'node', 6 | transform: { 7 | '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], 8 | }, 9 | moduleNameMapper: { 10 | '^@mux/mux-node$': '/src/index.ts', 11 | '^@mux/mux-node/_shims/auto/(.*)$': '/src/_shims/auto/$1-node', 12 | '^@mux/mux-node/(.*)$': '/src/$1', 13 | }, 14 | modulePathIgnorePatterns: [ 15 | '/ecosystem-tests/', 16 | '/dist/', 17 | '/deno/', 18 | '/deno_tests/', 19 | ], 20 | testPathIgnorePatterns: ['scripts'], 21 | }; 22 | 23 | export default config; 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mux/mux-node", 3 | "version": "11.1.0", 4 | "description": "The official TypeScript library for the Mux API", 5 | "author": "Mux ", 6 | "types": "dist/index.d.ts", 7 | "main": "dist/index.js", 8 | "type": "commonjs", 9 | "repository": "github:muxinc/mux-node-sdk", 10 | "license": "Apache-2.0", 11 | "packageManager": "yarn@1.22.22", 12 | "files": [ 13 | "**/*" 14 | ], 15 | "private": false, 16 | "scripts": { 17 | "test": "./scripts/test", 18 | "build": "./scripts/build", 19 | "prepublishOnly": "echo 'to publish, run yarn build && (cd dist; yarn publish)' && exit 1", 20 | "format": "prettier --write --cache --cache-strategy metadata . !dist", 21 | "prepare": "if ./scripts/utils/check-is-in-git-install.sh; then ./scripts/build && ./scripts/utils/git-swap.sh; fi", 22 | "tsn": "ts-node -r tsconfig-paths/register", 23 | "lint": "./scripts/lint", 24 | "fix": "./scripts/format" 25 | }, 26 | "dependencies": { 27 | "@types/node": "^18.11.18", 28 | "@types/node-fetch": "^2.6.4", 29 | "abort-controller": "^3.0.0", 30 | "agentkeepalive": "^4.2.1", 31 | "form-data-encoder": "1.7.2", 32 | "formdata-node": "^4.3.2", 33 | "jose": "^4.14.4", 34 | "node-fetch": "^2.6.7" 35 | }, 36 | "devDependencies": { 37 | "@swc/core": "^1.3.102", 38 | "@swc/jest": "^0.2.29", 39 | "@types/jest": "^29.4.0", 40 | "@typescript-eslint/eslint-plugin": "^6.7.0", 41 | "@typescript-eslint/parser": "^6.7.0", 42 | "eslint": "^8.49.0", 43 | "eslint-plugin-prettier": "^5.0.1", 44 | "eslint-plugin-unused-imports": "^3.0.0", 45 | "iconv-lite": "^0.6.3", 46 | "jest": "^29.4.0", 47 | "prettier": "^3.0.0", 48 | "ts-jest": "^29.1.0", 49 | "ts-node": "^10.5.0", 50 | "tsc-multi": "^1.1.0", 51 | "tsconfig-paths": "^4.0.0", 52 | "typescript": "^4.8.2" 53 | }, 54 | "sideEffects": [ 55 | "./_shims/index.js", 56 | "./_shims/index.mjs", 57 | "./shims/node.js", 58 | "./shims/node.mjs", 59 | "./shims/web.js", 60 | "./shims/web.mjs" 61 | ], 62 | "imports": { 63 | "@mux/mux-node": ".", 64 | "@mux/mux-node/*": "./src/*" 65 | }, 66 | "exports": { 67 | "./_shims/auto/*": { 68 | "deno": { 69 | "types": "./dist/_shims/auto/*.d.ts", 70 | "require": "./dist/_shims/auto/*.js", 71 | "default": "./dist/_shims/auto/*.mjs" 72 | }, 73 | "bun": { 74 | "types": "./dist/_shims/auto/*.d.ts", 75 | "require": "./dist/_shims/auto/*-bun.js", 76 | "default": "./dist/_shims/auto/*-bun.mjs" 77 | }, 78 | "browser": { 79 | "types": "./dist/_shims/auto/*.d.ts", 80 | "require": "./dist/_shims/auto/*.js", 81 | "default": "./dist/_shims/auto/*.mjs" 82 | }, 83 | "worker": { 84 | "types": "./dist/_shims/auto/*.d.ts", 85 | "require": "./dist/_shims/auto/*.js", 86 | "default": "./dist/_shims/auto/*.mjs" 87 | }, 88 | "workerd": { 89 | "types": "./dist/_shims/auto/*.d.ts", 90 | "require": "./dist/_shims/auto/*.js", 91 | "default": "./dist/_shims/auto/*.mjs" 92 | }, 93 | "node": { 94 | "types": "./dist/_shims/auto/*-node.d.ts", 95 | "require": "./dist/_shims/auto/*-node.js", 96 | "default": "./dist/_shims/auto/*-node.mjs" 97 | }, 98 | "types": "./dist/_shims/auto/*.d.ts", 99 | "require": "./dist/_shims/auto/*.js", 100 | "default": "./dist/_shims/auto/*.mjs" 101 | }, 102 | ".": { 103 | "require": { 104 | "types": "./dist/index.d.ts", 105 | "default": "./dist/index.js" 106 | }, 107 | "types": "./dist/index.d.mts", 108 | "default": "./dist/index.mjs" 109 | }, 110 | "./*.mjs": { 111 | "types": "./dist/*.d.ts", 112 | "default": "./dist/*.mjs" 113 | }, 114 | "./*.js": { 115 | "types": "./dist/*.d.ts", 116 | "default": "./dist/*.js" 117 | }, 118 | "./*": { 119 | "types": "./dist/*.d.ts", 120 | "require": "./dist/*.js", 121 | "default": "./dist/*.mjs" 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /release-please-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": { 3 | ".": {} 4 | }, 5 | "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", 6 | "include-v-in-tag": true, 7 | "include-component-in-tag": false, 8 | "versioning": "prerelease", 9 | "prerelease": true, 10 | "bump-minor-pre-major": true, 11 | "bump-patch-for-minor-pre-major": false, 12 | "pull-request-header": "Automated Release PR", 13 | "pull-request-title-pattern": "release: ${version}", 14 | "changelog-sections": [ 15 | { 16 | "type": "feat", 17 | "section": "Features" 18 | }, 19 | { 20 | "type": "fix", 21 | "section": "Bug Fixes" 22 | }, 23 | { 24 | "type": "perf", 25 | "section": "Performance Improvements" 26 | }, 27 | { 28 | "type": "revert", 29 | "section": "Reverts" 30 | }, 31 | { 32 | "type": "chore", 33 | "section": "Chores" 34 | }, 35 | { 36 | "type": "docs", 37 | "section": "Documentation" 38 | }, 39 | { 40 | "type": "style", 41 | "section": "Styles" 42 | }, 43 | { 44 | "type": "refactor", 45 | "section": "Refactors" 46 | }, 47 | { 48 | "type": "test", 49 | "section": "Tests", 50 | "hidden": true 51 | }, 52 | { 53 | "type": "build", 54 | "section": "Build System" 55 | }, 56 | { 57 | "type": "ci", 58 | "section": "Continuous Integration", 59 | "hidden": true 60 | } 61 | ], 62 | "reviewers": [ 63 | "@muxinc/api-sdk" 64 | ], 65 | "release-type": "node", 66 | "extra-files": [ 67 | "src/version.ts", 68 | "README.md" 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /scripts/bootstrap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then 8 | brew bundle check >/dev/null 2>&1 || { 9 | echo "==> Installing Homebrew dependencies…" 10 | brew bundle 11 | } 12 | fi 13 | 14 | echo "==> Installing Node dependencies…" 15 | 16 | PACKAGE_MANAGER=$(command -v yarn >/dev/null 2>&1 && echo "yarn" || echo "npm") 17 | 18 | $PACKAGE_MANAGER install 19 | -------------------------------------------------------------------------------- /scripts/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -exuo pipefail 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | node scripts/utils/check-version.cjs 8 | 9 | # Build into dist and will publish the package from there, 10 | # so that src/resources/foo.ts becomes /resources/foo.js 11 | # This way importing from `"@mux/mux-node/resources/foo"` works 12 | # even with `"moduleResolution": "node"` 13 | 14 | rm -rf dist; mkdir dist 15 | # Copy src to dist/src and build from dist/src into dist, so that 16 | # the source map for index.js.map will refer to ./src/index.ts etc 17 | cp -rp src README.md dist 18 | rm dist/src/_shims/*-deno.ts dist/src/_shims/auto/*-deno.ts 19 | for file in LICENSE CHANGELOG.md; do 20 | if [ -e "${file}" ]; then cp "${file}" dist; fi 21 | done 22 | if [ -e "bin/cli" ]; then 23 | mkdir dist/bin 24 | cp -p "bin/cli" dist/bin/; 25 | fi 26 | # this converts the export map paths for the dist directory 27 | # and does a few other minor things 28 | node scripts/utils/make-dist-package-json.cjs > dist/package.json 29 | 30 | # build to .js/.mjs/.d.ts files 31 | npm exec tsc-multi 32 | # copy over handwritten .js/.mjs/.d.ts files 33 | cp src/_shims/*.{d.ts,js,mjs,md} dist/_shims 34 | cp src/_shims/auto/*.{d.ts,js,mjs} dist/_shims/auto 35 | # we need to add exports = module.exports = Mux to index.js; 36 | # No way to get that from index.ts because it would cause compile errors 37 | # when building .mjs 38 | node scripts/utils/fix-index-exports.cjs 39 | # with "moduleResolution": "nodenext", if ESM resolves to index.d.ts, 40 | # it'll have TS errors on the default import. But if it resolves to 41 | # index.d.mts the default import will work (even though both files have 42 | # the same export default statement) 43 | cp dist/index.d.ts dist/index.d.mts 44 | cp tsconfig.dist-src.json dist/src/tsconfig.json 45 | 46 | node scripts/utils/postprocess-files.cjs 47 | 48 | # make sure that nothing crashes when we require the output CJS or 49 | # import the output ESM 50 | (cd dist && node -e 'require("@mux/mux-node")') 51 | (cd dist && node -e 'import("@mux/mux-node")' --input-type=module) 52 | 53 | if [ -e ./scripts/build-deno ] 54 | then 55 | ./scripts/build-deno 56 | fi 57 | -------------------------------------------------------------------------------- /scripts/format: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | echo "==> Running eslint --fix" 8 | ESLINT_USE_FLAT_CONFIG="false" ./node_modules/.bin/eslint --fix --ext ts,js . 9 | -------------------------------------------------------------------------------- /scripts/lint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | echo "==> Running eslint" 8 | ESLINT_USE_FLAT_CONFIG="false" ./node_modules/.bin/eslint --ext ts,js . 9 | 10 | echo "==> Running tsc" 11 | ./node_modules/.bin/tsc --noEmit 12 | -------------------------------------------------------------------------------- /scripts/mock: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | if [[ -n "$1" && "$1" != '--'* ]]; then 8 | URL="$1" 9 | shift 10 | else 11 | URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" 12 | fi 13 | 14 | # Check if the URL is empty 15 | if [ -z "$URL" ]; then 16 | echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" 17 | exit 1 18 | fi 19 | 20 | echo "==> Starting mock server with URL ${URL}" 21 | 22 | # Run prism mock on the given spec 23 | if [ "$1" == "--daemon" ]; then 24 | npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" &> .prism.log & 25 | 26 | # Wait for server to come online 27 | echo -n "Waiting for server" 28 | while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do 29 | echo -n "." 30 | sleep 0.1 31 | done 32 | 33 | if grep -q "✖ fatal" ".prism.log"; then 34 | cat .prism.log 35 | exit 1 36 | fi 37 | 38 | echo 39 | else 40 | npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" 41 | fi 42 | -------------------------------------------------------------------------------- /scripts/test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | RED='\033[0;31m' 8 | GREEN='\033[0;32m' 9 | YELLOW='\033[0;33m' 10 | NC='\033[0m' # No Color 11 | 12 | function prism_is_running() { 13 | curl --silent "http://localhost:4010" >/dev/null 2>&1 14 | } 15 | 16 | kill_server_on_port() { 17 | pids=$(lsof -t -i tcp:"$1" || echo "") 18 | if [ "$pids" != "" ]; then 19 | kill "$pids" 20 | echo "Stopped $pids." 21 | fi 22 | } 23 | 24 | function is_overriding_api_base_url() { 25 | [ -n "$TEST_API_BASE_URL" ] 26 | } 27 | 28 | if ! is_overriding_api_base_url && ! prism_is_running ; then 29 | # When we exit this script, make sure to kill the background mock server process 30 | trap 'kill_server_on_port 4010' EXIT 31 | 32 | # Start the dev server 33 | ./scripts/mock --daemon 34 | fi 35 | 36 | if is_overriding_api_base_url ; then 37 | echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" 38 | echo 39 | elif ! prism_is_running ; then 40 | echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" 41 | echo -e "running against your OpenAPI spec." 42 | echo 43 | echo -e "To run the server, pass in the path or url of your OpenAPI" 44 | echo -e "spec to the prism command:" 45 | echo 46 | echo -e " \$ ${YELLOW}npm exec --package=@stoplight/prism-cli@~5.3.2 -- prism mock path/to/your.openapi.yml${NC}" 47 | echo 48 | 49 | exit 1 50 | else 51 | echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" 52 | echo 53 | fi 54 | 55 | echo "==> Running tests" 56 | ./node_modules/.bin/jest "$@" 57 | -------------------------------------------------------------------------------- /scripts/utils/check-is-in-git-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Check if you happen to call prepare for a repository that's already in node_modules. 3 | [ "$(basename "$(dirname "$PWD")")" = 'node_modules' ] || 4 | # The name of the containing directory that 'npm` uses, which looks like 5 | # $HOME/.npm/_cacache/git-cloneXXXXXX 6 | [ "$(basename "$(dirname "$PWD")")" = 'tmp' ] || 7 | # The name of the containing directory that 'yarn` uses, which looks like 8 | # $(yarn cache dir)/.tmp/XXXXX 9 | [ "$(basename "$(dirname "$PWD")")" = '.tmp' ] 10 | -------------------------------------------------------------------------------- /scripts/utils/check-version.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const main = () => { 5 | const pkg = require('../../package.json'); 6 | const version = pkg['version']; 7 | if (!version) throw 'The version property is not set in the package.json file'; 8 | if (typeof version !== 'string') { 9 | throw `Unexpected type for the package.json version field; got ${typeof version}, expected string`; 10 | } 11 | 12 | const versionFile = path.resolve(__dirname, '..', '..', 'src', 'version.ts'); 13 | const contents = fs.readFileSync(versionFile, 'utf8'); 14 | const output = contents.replace(/(export const VERSION = ')(.*)(')/g, `$1${version}$3`); 15 | fs.writeFileSync(versionFile, output); 16 | }; 17 | 18 | if (require.main === module) { 19 | main(); 20 | } 21 | -------------------------------------------------------------------------------- /scripts/utils/fix-index-exports.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const indexJs = 5 | process.env['DIST_PATH'] ? 6 | path.resolve(process.env['DIST_PATH'], 'index.js') 7 | : path.resolve(__dirname, '..', '..', 'dist', 'index.js'); 8 | 9 | let before = fs.readFileSync(indexJs, 'utf8'); 10 | let after = before.replace( 11 | /^\s*exports\.default\s*=\s*(\w+)/m, 12 | 'exports = module.exports = $1;\nexports.default = $1', 13 | ); 14 | fs.writeFileSync(indexJs, after, 'utf8'); 15 | -------------------------------------------------------------------------------- /scripts/utils/git-swap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exuo pipefail 3 | # the package is published to NPM from ./dist 4 | # we want the final file structure for git installs to match the npm installs, so we 5 | 6 | # delete everything except ./dist and ./node_modules 7 | find . -maxdepth 1 -mindepth 1 ! -name 'dist' ! -name 'node_modules' -exec rm -rf '{}' + 8 | 9 | # move everything from ./dist to . 10 | mv dist/* . 11 | 12 | # delete the now-empty ./dist 13 | rmdir dist 14 | -------------------------------------------------------------------------------- /scripts/utils/make-dist-package-json.cjs: -------------------------------------------------------------------------------- 1 | const pkgJson = require(process.env['PKG_JSON_PATH'] || '../../package.json'); 2 | 3 | function processExportMap(m) { 4 | for (const key in m) { 5 | const value = m[key]; 6 | if (typeof value === 'string') m[key] = value.replace(/^\.\/dist\//, './'); 7 | else processExportMap(value); 8 | } 9 | } 10 | processExportMap(pkgJson.exports); 11 | 12 | for (const key of ['types', 'main', 'module']) { 13 | if (typeof pkgJson[key] === 'string') pkgJson[key] = pkgJson[key].replace(/^(\.\/)?dist\//, './'); 14 | } 15 | 16 | delete pkgJson.devDependencies; 17 | delete pkgJson.scripts.prepack; 18 | delete pkgJson.scripts.prepublishOnly; 19 | delete pkgJson.scripts.prepare; 20 | 21 | console.log(JSON.stringify(pkgJson, null, 2)); 22 | -------------------------------------------------------------------------------- /scripts/utils/postprocess-files.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const { parse } = require('@typescript-eslint/parser'); 4 | 5 | const pkgImportPath = process.env['PKG_IMPORT_PATH'] ?? '@mux/mux-node/'; 6 | 7 | const distDir = 8 | process.env['DIST_PATH'] ? 9 | path.resolve(process.env['DIST_PATH']) 10 | : path.resolve(__dirname, '..', '..', 'dist'); 11 | const distSrcDir = path.join(distDir, 'src'); 12 | 13 | /** 14 | * Quick and dirty AST traversal 15 | */ 16 | function traverse(node, visitor) { 17 | if (!node || typeof node.type !== 'string') return; 18 | visitor.node?.(node); 19 | visitor[node.type]?.(node); 20 | for (const key in node) { 21 | const value = node[key]; 22 | if (Array.isArray(value)) { 23 | for (const elem of value) traverse(elem, visitor); 24 | } else if (value instanceof Object) { 25 | traverse(value, visitor); 26 | } 27 | } 28 | } 29 | 30 | /** 31 | * Helper method for replacing arbitrary ranges of text in input code. 32 | * 33 | * The `replacer` is a function that will be called with a mini-api. For example: 34 | * 35 | * replaceRanges('foobar', ({ replace }) => replace([0, 3], 'baz')) // 'bazbar' 36 | * 37 | * The replaced ranges must not be overlapping. 38 | */ 39 | function replaceRanges(code, replacer) { 40 | const replacements = []; 41 | replacer({ replace: (range, replacement) => replacements.push({ range, replacement }) }); 42 | 43 | if (!replacements.length) return code; 44 | replacements.sort((a, b) => a.range[0] - b.range[0]); 45 | const overlapIndex = replacements.findIndex( 46 | (r, index) => index > 0 && replacements[index - 1].range[1] > r.range[0], 47 | ); 48 | if (overlapIndex >= 0) { 49 | throw new Error( 50 | `replacements overlap: ${JSON.stringify(replacements[overlapIndex - 1])} and ${JSON.stringify( 51 | replacements[overlapIndex], 52 | )}`, 53 | ); 54 | } 55 | 56 | const parts = []; 57 | let end = 0; 58 | for (const { 59 | range: [from, to], 60 | replacement, 61 | } of replacements) { 62 | if (from > end) parts.push(code.substring(end, from)); 63 | parts.push(replacement); 64 | end = to; 65 | } 66 | if (end < code.length) parts.push(code.substring(end)); 67 | return parts.join(''); 68 | } 69 | 70 | /** 71 | * Like calling .map(), where the iteratee is called on the path in every import or export from statement. 72 | * @returns the transformed code 73 | */ 74 | function mapModulePaths(code, iteratee) { 75 | const ast = parse(code, { range: true }); 76 | return replaceRanges(code, ({ replace }) => 77 | traverse(ast, { 78 | node(node) { 79 | switch (node.type) { 80 | case 'ImportDeclaration': 81 | case 'ExportNamedDeclaration': 82 | case 'ExportAllDeclaration': 83 | case 'ImportExpression': 84 | if (node.source) { 85 | const { range, value } = node.source; 86 | const transformed = iteratee(value); 87 | if (transformed !== value) { 88 | replace(range, JSON.stringify(transformed)); 89 | } 90 | } 91 | } 92 | }, 93 | }), 94 | ); 95 | } 96 | 97 | async function* walk(dir) { 98 | for await (const d of await fs.promises.opendir(dir)) { 99 | const entry = path.join(dir, d.name); 100 | if (d.isDirectory()) yield* walk(entry); 101 | else if (d.isFile()) yield entry; 102 | } 103 | } 104 | 105 | async function postprocess() { 106 | for await (const file of walk(path.resolve(__dirname, '..', '..', 'dist'))) { 107 | if (!/\.([cm]?js|(\.d)?[cm]?ts)$/.test(file)) continue; 108 | 109 | const code = await fs.promises.readFile(file, 'utf8'); 110 | 111 | let transformed = mapModulePaths(code, (importPath) => { 112 | if (file.startsWith(distSrcDir)) { 113 | if (importPath.startsWith(pkgImportPath)) { 114 | // convert self-references in dist/src to relative paths 115 | let relativePath = path.relative( 116 | path.dirname(file), 117 | path.join(distSrcDir, importPath.substring(pkgImportPath.length)), 118 | ); 119 | if (!relativePath.startsWith('.')) relativePath = `./${relativePath}`; 120 | return relativePath; 121 | } 122 | return importPath; 123 | } 124 | if (importPath.startsWith('.')) { 125 | // add explicit file extensions to relative imports 126 | const { dir, name } = path.parse(importPath); 127 | const ext = /\.mjs$/.test(file) ? '.mjs' : '.js'; 128 | return `${dir}/${name}${ext}`; 129 | } 130 | return importPath; 131 | }); 132 | 133 | if (file.startsWith(distSrcDir) && !file.endsWith('_shims/index.d.ts')) { 134 | // strip out `unknown extends Foo ? never :` shim guards in dist/src 135 | // to prevent errors from appearing in Go To Source 136 | transformed = transformed.replace( 137 | new RegExp('unknown extends (typeof )?\\S+ \\? \\S+ :\\s*'.replace(/\s+/, '\\s+'), 'gm'), 138 | // replace with same number of characters to avoid breaking source maps 139 | (match) => ' '.repeat(match.length), 140 | ); 141 | } 142 | 143 | if (file.endsWith('.d.ts')) { 144 | // work around bad tsc behavior 145 | // if we have `import { type Readable } from '@mux/mux-node/_shims/index'`, 146 | // tsc sometimes replaces `Readable` with `import("stream").Readable` inline 147 | // in the output .d.ts 148 | transformed = transformed.replace(/import\("stream"\).Readable/g, 'Readable'); 149 | } 150 | 151 | // strip out lib="dom" and types="node" references; these are needed at build time, 152 | // but would pollute the user's TS environment 153 | transformed = transformed.replace( 154 | /^ *\/\/\/ * ' '.repeat(match.length - 1) + '\n', 157 | ); 158 | 159 | if (transformed !== code) { 160 | await fs.promises.writeFile(file, transformed, 'utf8'); 161 | console.error(`wrote ${path.relative(process.cwd(), file)}`); 162 | } 163 | } 164 | } 165 | postprocess(); 166 | -------------------------------------------------------------------------------- /scripts/utils/upload-artifact.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exuo pipefail 3 | 4 | RESPONSE=$(curl -X POST "$URL" \ 5 | -H "Authorization: Bearer $AUTH" \ 6 | -H "Content-Type: application/json") 7 | 8 | SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url') 9 | 10 | if [[ "$SIGNED_URL" == "null" ]]; then 11 | echo -e "\033[31mFailed to get signed URL.\033[0m" 12 | exit 1 13 | fi 14 | 15 | UPLOAD_RESPONSE=$(tar -cz dist | curl -v -X PUT \ 16 | -H "Content-Type: application/gzip" \ 17 | --data-binary @- "$SIGNED_URL" 2>&1) 18 | 19 | if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then 20 | echo -e "\033[32mUploaded build to Stainless storage.\033[0m" 21 | echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/mux-node/$SHA'\033[0m" 22 | else 23 | echo -e "\033[31mFailed to upload artifact.\033[0m" 24 | exit 1 25 | fi 26 | -------------------------------------------------------------------------------- /src/_shims/MultipartBody.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export class MultipartBody { 5 | constructor(public body: any) {} 6 | get [Symbol.toStringTag](): string { 7 | return 'MultipartBody'; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/_shims/README.md: -------------------------------------------------------------------------------- 1 | # 👋 Wondering what everything in here does? 2 | 3 | `@mux/mux-node` supports a wide variety of runtime environments like Node.js, Deno, Bun, browsers, and various 4 | edge runtimes, as well as both CommonJS (CJS) and EcmaScript Modules (ESM). 5 | 6 | To do this, `@mux/mux-node` provides shims for either using `node-fetch` when in Node (because `fetch` is still experimental there) or the global `fetch` API built into the environment when not in Node. 7 | 8 | It uses [conditional exports](https://nodejs.org/api/packages.html#conditional-exports) to 9 | automatically select the correct shims for each environment. However, conditional exports are a fairly new 10 | feature and not supported everywhere. For instance, the TypeScript `"moduleResolution": "node"` 11 | 12 | setting doesn't consult the `exports` map, compared to `"moduleResolution": "nodeNext"`, which does. 13 | Unfortunately that's still the default setting, and it can result in errors like 14 | getting the wrong raw `Response` type from `.asResponse()`, for example. 15 | 16 | The user can work around these issues by manually importing one of: 17 | 18 | - `import '@mux/mux-node/shims/node'` 19 | - `import '@mux/mux-node/shims/web'` 20 | 21 | All of the code here in `_shims` handles selecting the automatic default shims or manual overrides. 22 | 23 | ### How it works - Runtime 24 | 25 | Runtime shims get installed by calling `setShims` exported by `@mux/mux-node/_shims/registry`. 26 | 27 | Manually importing `@mux/mux-node/shims/node` or `@mux/mux-node/shims/web`, calls `setShims` with the respective runtime shims. 28 | 29 | All client code imports shims from `@mux/mux-node/_shims/index`, which: 30 | 31 | - checks if shims have been set manually 32 | - if not, calls `setShims` with the shims from `@mux/mux-node/_shims/auto/runtime` 33 | - re-exports the installed shims from `@mux/mux-node/_shims/registry`. 34 | 35 | `@mux/mux-node/_shims/auto/runtime` exports web runtime shims. 36 | If the `node` export condition is set, the export map replaces it with `@mux/mux-node/_shims/auto/runtime-node`. 37 | 38 | ### How it works - Type time 39 | 40 | All client code imports shim types from `@mux/mux-node/_shims/index`, which selects the manual types from `@mux/mux-node/_shims/manual-types` if they have been declared, otherwise it exports the auto types from `@mux/mux-node/_shims/auto/types`. 41 | 42 | `@mux/mux-node/_shims/manual-types` exports an empty namespace. 43 | Manually importing `@mux/mux-node/shims/node` or `@mux/mux-node/shims/web` merges declarations into this empty namespace, so they get picked up by `@mux/mux-node/_shims/index`. 44 | 45 | `@mux/mux-node/_shims/auto/types` exports web type definitions. 46 | If the `node` export condition is set, the export map replaces it with `@mux/mux-node/_shims/auto/types-node`, though TS only picks this up if `"moduleResolution": "nodenext"` or `"moduleResolution": "bundler"`. 47 | -------------------------------------------------------------------------------- /src/_shims/auto/jwt-bun.ts: -------------------------------------------------------------------------------- 1 | export * from './jwt-node'; 2 | -------------------------------------------------------------------------------- /src/_shims/auto/jwt-deno.ts: -------------------------------------------------------------------------------- 1 | import { Mux } from '../../index.ts'; 2 | import { KeyLike, SignJWT, importPKCS8 } from 'https://deno.land/x/jose@v4.14.4/index.ts'; 3 | import { SignOptions, MuxJWTSignOptions } from '../../util/jwt-types.js'; 4 | import { unwrapPem, pkcs1to8, toPkcs8Pem, isKeyLike, keyFormatErrorMessage } from '../../util/jwt-util.js'; 5 | 6 | export type PrivateKey = KeyLike; 7 | 8 | export function sign( 9 | payload: object, 10 | secretOrPrivateKey: KeyLike | Uint8Array, 11 | options: SignOptions, 12 | ): Promise { 13 | const sign = new SignJWT({ 14 | ...(payload as any), 15 | ...(options.keyid ? { kid: options.keyid } : null), 16 | }).setProtectedHeader({ alg: options.algorithm || 'RS256' }); 17 | if (options.issuer) sign.setIssuer(options.issuer); 18 | if (options.subject) sign.setSubject(options.subject); 19 | if (options.audience) sign.setAudience(options.audience); 20 | if (options.notBefore) sign.setNotBefore(options.notBefore); 21 | if (options.expiresIn) sign.setExpirationTime(options.expiresIn); 22 | return sign.sign(secretOrPrivateKey); 23 | } 24 | 25 | export function getSigningKey(mux: Mux, opts: MuxJWTSignOptions): string { 26 | const keyId = opts.keyId || mux.jwtSigningKey; 27 | if (!keyId) { 28 | throw new Error( 29 | 'Signing key required; pass a keyId option to mux.jwt.sign*(), a jwtSigningKey option to new Mux(), or set the MUX_SIGNING_KEY environment variable', 30 | ); 31 | } 32 | 33 | return keyId; 34 | } 35 | 36 | export async function getPrivateKey(mux: Mux, opts: MuxJWTSignOptions): Promise { 37 | let key = await getPrivateKeyHelper(mux, opts); 38 | if (typeof key === 'string') { 39 | if (key.startsWith('-----BEGIN RSA PRIVATE')) { 40 | key = toPkcs8Pem(pkcs1to8(unwrapPem(key))); 41 | } 42 | return await importPKCS8(key, 'RS256'); 43 | } else if (key instanceof Uint8Array) { 44 | return await importPKCS8(toPkcs8Pem(pkcs1to8(key)), 'RS256'); 45 | } else if (isKeyLike(key)) { 46 | return key; 47 | } 48 | throw new TypeError(keyFormatErrorMessage); 49 | } 50 | 51 | async function getPrivateKeyHelper(mux: Mux, opts: MuxJWTSignOptions): Promise { 52 | let key; 53 | if (opts.keySecret) { 54 | key = opts.keySecret; 55 | } else if (opts.keyFilePath) { 56 | throw new Error(`keyFilePath is not supported in this environment`); 57 | } else if (mux.jwtPrivateKey) { 58 | key = mux.jwtPrivateKey; 59 | } 60 | 61 | if (isKeyLike(key)) return key; 62 | 63 | if (typeof key === 'string') { 64 | key = key.trim(); 65 | if (key.startsWith('-----BEGIN')) { 66 | return key; 67 | } 68 | 69 | try { 70 | key = atob(key); 71 | if (key.startsWith('-----BEGIN')) { 72 | return key; 73 | } 74 | } catch (error) { 75 | // fallthrough 76 | } 77 | 78 | throw new TypeError(keyFormatErrorMessage); 79 | } 80 | 81 | throw new TypeError( 82 | 'Private key required; pass a keySecret option to mux.jwt.sign*(), a jwtPrivateKey option to new Mux(), or set the MUX_PRIVATE_KEY environment variable', 83 | ); 84 | } 85 | -------------------------------------------------------------------------------- /src/_shims/auto/jwt-node.ts: -------------------------------------------------------------------------------- 1 | import { Mux } from '../../index'; 2 | import { KeyLike, SignJWT } from 'jose'; 3 | import fs from 'fs'; 4 | import { SignOptions, MuxJWTSignOptions } from '../../util/jwt-types'; 5 | import { isKeyLike, keyFormatErrorMessage } from '../../util/jwt-util'; 6 | import { createPrivateKey } from 'crypto'; 7 | 8 | export type PrivateKey = Buffer | KeyLike; 9 | 10 | export function sign( 11 | payload: object, 12 | secretOrPrivateKey: KeyLike | Uint8Array, 13 | options: SignOptions, 14 | ): Promise { 15 | const sign = new SignJWT({ 16 | ...(payload as any), 17 | ...(options.keyid ? { kid: options.keyid } : null), 18 | }).setProtectedHeader({ alg: options.algorithm || 'RS256' }); 19 | if (options.issuer) sign.setIssuer(options.issuer); 20 | if (options.subject) sign.setSubject(options.subject); 21 | if (options.audience) sign.setAudience(options.audience); 22 | if (options.notBefore) sign.setNotBefore(options.notBefore); 23 | if (options.expiresIn) sign.setExpirationTime(options.expiresIn); 24 | return sign.sign(secretOrPrivateKey); 25 | } 26 | 27 | export function getSigningKey(mux: Mux, opts: MuxJWTSignOptions): string { 28 | const keyId = opts.keyId || mux.jwtSigningKey; 29 | if (!keyId) { 30 | throw new Error( 31 | 'Signing key required; pass a keyId option to mux.jwt.sign*(), a jwtSigningKey option to new Mux(), or set the MUX_SIGNING_KEY environment variable', 32 | ); 33 | } 34 | 35 | return keyId; 36 | } 37 | 38 | export async function getPrivateKey(mux: Mux, opts: MuxJWTSignOptions): Promise { 39 | const key = await getPrivateKeyHelper(mux, opts); 40 | if (isKeyLike(key)) return key; 41 | return createPrivateKey(key as any); 42 | } 43 | async function getPrivateKeyHelper(mux: Mux, opts: MuxJWTSignOptions): Promise { 44 | let key; 45 | if (opts.keySecret) { 46 | key = opts.keySecret; 47 | } else if (opts.keyFilePath) { 48 | key = await fs.promises.readFile(opts.keyFilePath, 'utf8'); 49 | } else if (mux.jwtPrivateKey) { 50 | key = mux.jwtPrivateKey; 51 | } 52 | 53 | if (Buffer.isBuffer(key) || isKeyLike(key)) return key; 54 | 55 | if (typeof key === 'string') { 56 | key = key.trim(); 57 | if (key.startsWith('-----BEGIN')) { 58 | return key; 59 | } 60 | 61 | try { 62 | key = Buffer.from(key, 'base64').toString(); 63 | if (key.startsWith('-----BEGIN')) { 64 | return key; 65 | } 66 | } catch (err) { 67 | // fallthrough 68 | } 69 | 70 | throw new TypeError(keyFormatErrorMessage); 71 | } 72 | 73 | throw new TypeError( 74 | 'Private key required; pass a keySecret or keyFilePath option to mux.jwt.sign*(), a jwtPrivateKey option to new Mux(), or set the MUX_PRIVATE_KEY environment variable', 75 | ); 76 | } 77 | -------------------------------------------------------------------------------- /src/_shims/auto/jwt.ts: -------------------------------------------------------------------------------- 1 | import { Mux } from '../../index'; 2 | import { KeyLike, SignJWT, importPKCS8 } from 'jose'; 3 | import { SignOptions, MuxJWTSignOptions } from '../../util/jwt-types'; 4 | import { unwrapPem, pkcs1to8, toPkcs8Pem, isKeyLike, keyFormatErrorMessage } from '../../util/jwt-util'; 5 | 6 | export type PrivateKey = KeyLike; 7 | 8 | export function sign( 9 | payload: object, 10 | secretOrPrivateKey: KeyLike | Uint8Array, 11 | options: SignOptions, 12 | ): Promise { 13 | const sign = new SignJWT({ 14 | ...(payload as any), 15 | ...(options.keyid ? { kid: options.keyid } : null), 16 | }).setProtectedHeader({ alg: options.algorithm || 'RS256' }); 17 | if (options.issuer) sign.setIssuer(options.issuer); 18 | if (options.subject) sign.setSubject(options.subject); 19 | if (options.audience) sign.setAudience(options.audience); 20 | if (options.notBefore) sign.setNotBefore(options.notBefore); 21 | if (options.expiresIn) sign.setExpirationTime(options.expiresIn); 22 | return sign.sign(secretOrPrivateKey); 23 | } 24 | 25 | export function getSigningKey(mux: Mux, opts: MuxJWTSignOptions): string { 26 | const keyId = opts.keyId || mux.jwtSigningKey; 27 | if (!keyId) { 28 | throw new Error( 29 | 'Signing key required; pass a keyId option to mux.jwt.sign*(), a jwtSigningKey option to new Mux(), or set the MUX_SIGNING_KEY environment variable', 30 | ); 31 | } 32 | 33 | return keyId; 34 | } 35 | 36 | export async function getPrivateKey(mux: Mux, opts: MuxJWTSignOptions): Promise { 37 | let key = await getPrivateKeyHelper(mux, opts); 38 | if (typeof key === 'string') { 39 | if (key.startsWith('-----BEGIN RSA PRIVATE')) { 40 | key = toPkcs8Pem(pkcs1to8(unwrapPem(key))); 41 | } 42 | return await importPKCS8(key, 'RS256'); 43 | } else if (key instanceof Uint8Array) { 44 | return await importPKCS8(toPkcs8Pem(pkcs1to8(key)), 'RS256'); 45 | } else if (isKeyLike(key)) { 46 | return key; 47 | } 48 | throw new TypeError(keyFormatErrorMessage); 49 | } 50 | 51 | async function getPrivateKeyHelper(mux: Mux, opts: MuxJWTSignOptions): Promise { 52 | let key; 53 | if (opts.keySecret) { 54 | key = opts.keySecret; 55 | } else if (opts.keyFilePath) { 56 | throw new Error(`keyFilePath is not supported in this environment`); 57 | } else if (mux.jwtPrivateKey) { 58 | key = mux.jwtPrivateKey; 59 | } 60 | 61 | if (isKeyLike(key)) return key; 62 | 63 | if (typeof key === 'string') { 64 | key = key.trim(); 65 | if (key.startsWith('-----BEGIN')) { 66 | return key; 67 | } 68 | 69 | try { 70 | key = atob(key); 71 | if (key.startsWith('-----BEGIN')) { 72 | return key; 73 | } 74 | } catch (error) { 75 | // fallthrough 76 | } 77 | 78 | throw new TypeError(keyFormatErrorMessage); 79 | } 80 | 81 | throw new TypeError( 82 | 'Private key required; pass a keySecret option to mux.jwt.sign*(), a jwtPrivateKey option to new Mux(), or set the MUX_PRIVATE_KEY environment variable', 83 | ); 84 | } 85 | -------------------------------------------------------------------------------- /src/_shims/auto/runtime-bun.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../bun-runtime'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/runtime-deno.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../web-runtime'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/runtime-node.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../node-runtime'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/runtime.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../web-runtime'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/types-deno.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../web-types'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/types-node.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../node-types'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export type Agent = any; 5 | 6 | // @ts-ignore 7 | declare const _fetch: unknown extends typeof fetch ? never : typeof fetch; 8 | export { _fetch as fetch }; 9 | 10 | // @ts-ignore 11 | type _Request = unknown extends Request ? never : Request; 12 | export { _Request as Request }; 13 | 14 | // @ts-ignore 15 | type _RequestInfo = unknown extends RequestInfo ? never : RequestInfo; 16 | export { type _RequestInfo as RequestInfo }; 17 | 18 | // @ts-ignore 19 | type _RequestInit = unknown extends RequestInit ? never : RequestInit; 20 | export { type _RequestInit as RequestInit }; 21 | 22 | // @ts-ignore 23 | type _Response = unknown extends Response ? never : Response; 24 | export { _Response as Response }; 25 | 26 | // @ts-ignore 27 | type _ResponseInit = unknown extends ResponseInit ? never : ResponseInit; 28 | export { type _ResponseInit as ResponseInit }; 29 | 30 | // @ts-ignore 31 | type _ResponseType = unknown extends ResponseType ? never : ResponseType; 32 | export { type _ResponseType as ResponseType }; 33 | 34 | // @ts-ignore 35 | type _BodyInit = unknown extends BodyInit ? never : BodyInit; 36 | export { type _BodyInit as BodyInit }; 37 | 38 | // @ts-ignore 39 | type _Headers = unknown extends Headers ? never : Headers; 40 | export { _Headers as Headers }; 41 | 42 | // @ts-ignore 43 | type _HeadersInit = unknown extends HeadersInit ? never : HeadersInit; 44 | export { type _HeadersInit as HeadersInit }; 45 | 46 | type EndingType = 'native' | 'transparent'; 47 | 48 | export interface BlobPropertyBag { 49 | endings?: EndingType; 50 | type?: string; 51 | } 52 | 53 | export interface FilePropertyBag extends BlobPropertyBag { 54 | lastModified?: number; 55 | } 56 | 57 | export type FileFromPathOptions = Omit; 58 | 59 | // @ts-ignore 60 | type _FormData = unknown extends FormData ? never : FormData; 61 | // @ts-ignore 62 | declare const _FormData: unknown extends typeof FormData ? never : typeof FormData; 63 | export { _FormData as FormData }; 64 | 65 | // @ts-ignore 66 | type _File = unknown extends File ? never : File; 67 | // @ts-ignore 68 | declare const _File: unknown extends typeof File ? never : typeof File; 69 | export { _File as File }; 70 | 71 | // @ts-ignore 72 | type _Blob = unknown extends Blob ? never : Blob; 73 | // @ts-ignore 74 | declare const _Blob: unknown extends typeof Blob ? never : typeof Blob; 75 | export { _Blob as Blob }; 76 | 77 | export declare class Readable { 78 | readable: boolean; 79 | readonly readableEnded: boolean; 80 | readonly readableFlowing: boolean | null; 81 | readonly readableHighWaterMark: number; 82 | readonly readableLength: number; 83 | readonly readableObjectMode: boolean; 84 | destroyed: boolean; 85 | read(size?: number): any; 86 | pause(): this; 87 | resume(): this; 88 | isPaused(): boolean; 89 | destroy(error?: Error): this; 90 | [Symbol.asyncIterator](): AsyncIterableIterator; 91 | } 92 | 93 | export declare class FsReadStream extends Readable { 94 | path: {}; // node type is string | Buffer 95 | } 96 | 97 | // @ts-ignore 98 | type _ReadableStream = unknown extends ReadableStream ? never : ReadableStream; 99 | // @ts-ignore 100 | declare const _ReadableStream: unknown extends typeof ReadableStream ? never : typeof ReadableStream; 101 | export { _ReadableStream as ReadableStream }; 102 | -------------------------------------------------------------------------------- /src/_shims/auto/types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/auto/types.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/bun-runtime.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import { type Shims } from './registry'; 5 | import { getRuntime as getWebRuntime } from './web-runtime'; 6 | import { ReadStream as FsReadStream } from 'node:fs'; 7 | 8 | export function getRuntime(): Shims { 9 | const runtime = getWebRuntime(); 10 | function isFsReadStream(value: any): value is FsReadStream { 11 | return value instanceof FsReadStream; 12 | } 13 | return { ...runtime, isFsReadStream }; 14 | } 15 | -------------------------------------------------------------------------------- /src/_shims/index-deno.ts: -------------------------------------------------------------------------------- 1 | import { MultipartBody } from './MultipartBody'; 2 | import { type RequestOptions } from '../core'; 3 | 4 | export const kind: string = 'web'; 5 | 6 | export type Agent = any; 7 | 8 | const _fetch = fetch; 9 | type _fetch = typeof fetch; 10 | export { _fetch as fetch }; 11 | 12 | const _Request = Request; 13 | type _Request = Request; 14 | export { _Request as Request }; 15 | 16 | type _RequestInfo = RequestInfo; 17 | export { type _RequestInfo as RequestInfo }; 18 | 19 | type _RequestInit = RequestInit; 20 | export { type _RequestInit as RequestInit }; 21 | 22 | const _Response = Response; 23 | type _Response = Response; 24 | export { _Response as Response }; 25 | 26 | type _ResponseInit = ResponseInit; 27 | export { type _ResponseInit as ResponseInit }; 28 | 29 | type _ResponseType = ResponseType; 30 | export { type _ResponseType as ResponseType }; 31 | 32 | type _BodyInit = BodyInit; 33 | export { type _BodyInit as BodyInit }; 34 | 35 | const _Headers = Headers; 36 | type _Headers = Headers; 37 | export { _Headers as Headers }; 38 | 39 | type _HeadersInit = HeadersInit; 40 | export { type _HeadersInit as HeadersInit }; 41 | 42 | type EndingType = 'native' | 'transparent'; 43 | 44 | export interface BlobPropertyBag { 45 | endings?: EndingType; 46 | type?: string; 47 | } 48 | 49 | export interface FilePropertyBag extends BlobPropertyBag { 50 | lastModified?: number; 51 | } 52 | 53 | export type FileFromPathOptions = Omit; 54 | 55 | const _FormData = FormData; 56 | type _FormData = FormData; 57 | export { _FormData as FormData }; 58 | 59 | const _File = File; 60 | type _File = File; 61 | export { _File as File }; 62 | 63 | const _Blob = Blob; 64 | type _Blob = Blob; 65 | export { _Blob as Blob }; 66 | 67 | export async function getMultipartRequestOptions>( 68 | form: FormData, 69 | opts: RequestOptions, 70 | ): Promise> { 71 | return { 72 | ...opts, 73 | body: new MultipartBody(form) as any, 74 | }; 75 | } 76 | 77 | export function getDefaultAgent(url: string) { 78 | return undefined; 79 | } 80 | export function fileFromPath() { 81 | throw new Error( 82 | 'The `fileFromPath` function is only supported in Node. See the README for more details: https://www.github.com/muxinc/mux-node-sdk#file-uploads', 83 | ); 84 | } 85 | 86 | export const isFsReadStream = (value: any) => false; 87 | 88 | export declare class Readable { 89 | readable: boolean; 90 | readonly readableEnded: boolean; 91 | readonly readableFlowing: boolean | null; 92 | readonly readableHighWaterMark: number; 93 | readonly readableLength: number; 94 | readonly readableObjectMode: boolean; 95 | destroyed: boolean; 96 | read(size?: number): any; 97 | pause(): this; 98 | resume(): this; 99 | isPaused(): boolean; 100 | destroy(error?: Error): this; 101 | [Symbol.asyncIterator](): AsyncIterableIterator; 102 | } 103 | 104 | export declare class FsReadStream extends Readable { 105 | path: {}; // node type is string | Buffer 106 | } 107 | 108 | const _ReadableStream = ReadableStream; 109 | type _ReadableStream = ReadableStream; 110 | export { _ReadableStream as ReadableStream }; 111 | 112 | export const init = () => {}; 113 | -------------------------------------------------------------------------------- /src/_shims/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import { manual } from './manual-types'; 5 | import * as auto from '@mux/mux-node/_shims/auto/types'; 6 | import { type RequestOptions } from '../core'; 7 | 8 | type SelectType = unknown extends Manual ? Auto : Manual; 9 | 10 | export const kind: string; 11 | 12 | // @ts-ignore 13 | export type Agent = SelectType; 14 | 15 | // @ts-ignore 16 | export const fetch: SelectType; 17 | 18 | // @ts-ignore 19 | export type Request = SelectType; 20 | // @ts-ignore 21 | export type RequestInfo = SelectType; 22 | // @ts-ignore 23 | export type RequestInit = SelectType; 24 | 25 | // @ts-ignore 26 | export type Response = SelectType; 27 | // @ts-ignore 28 | export type ResponseInit = SelectType; 29 | // @ts-ignore 30 | export type ResponseType = SelectType; 31 | // @ts-ignore 32 | export type BodyInit = SelectType; 33 | // @ts-ignore 34 | export type Headers = SelectType; 35 | // @ts-ignore 36 | export const Headers: SelectType; 37 | // @ts-ignore 38 | export type HeadersInit = SelectType; 39 | 40 | // @ts-ignore 41 | export type BlobPropertyBag = SelectType; 42 | // @ts-ignore 43 | export type FilePropertyBag = SelectType; 44 | // @ts-ignore 45 | export type FileFromPathOptions = SelectType; 46 | // @ts-ignore 47 | export type FormData = SelectType; 48 | // @ts-ignore 49 | export const FormData: SelectType; 50 | // @ts-ignore 51 | export type File = SelectType; 52 | // @ts-ignore 53 | export const File: SelectType; 54 | // @ts-ignore 55 | export type Blob = SelectType; 56 | // @ts-ignore 57 | export const Blob: SelectType; 58 | 59 | // @ts-ignore 60 | export type Readable = SelectType; 61 | // @ts-ignore 62 | export type FsReadStream = SelectType; 63 | // @ts-ignore 64 | export type ReadableStream = SelectType; 65 | // @ts-ignore 66 | export const ReadableStream: SelectType; 67 | 68 | export function getMultipartRequestOptions>( 69 | form: FormData, 70 | opts: RequestOptions, 71 | ): Promise>; 72 | 73 | export function getDefaultAgent(url: string): any; 74 | 75 | // @ts-ignore 76 | export type FileFromPathOptions = SelectType; 77 | 78 | export function fileFromPath(path: string, options?: FileFromPathOptions): Promise; 79 | export function fileFromPath(path: string, filename?: string, options?: FileFromPathOptions): Promise; 80 | 81 | export function isFsReadStream(value: any): value is FsReadStream; 82 | 83 | export const init: () => void; 84 | -------------------------------------------------------------------------------- /src/_shims/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | const shims = require('./registry'); 5 | const auto = require('@mux/mux-node/_shims/auto/runtime'); 6 | exports.init = () => { 7 | if (!shims.kind) shims.setShims(auto.getRuntime(), { auto: true }); 8 | }; 9 | for (const property of Object.keys(shims)) { 10 | Object.defineProperty(exports, property, { 11 | get() { 12 | return shims[property]; 13 | }, 14 | }); 15 | } 16 | 17 | exports.init(); 18 | -------------------------------------------------------------------------------- /src/_shims/index.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import * as shims from './registry.mjs'; 5 | import * as auto from '@mux/mux-node/_shims/auto/runtime'; 6 | export const init = () => { 7 | if (!shims.kind) shims.setShims(auto.getRuntime(), { auto: true }); 8 | }; 9 | export * from './registry.mjs'; 10 | 11 | init(); 12 | -------------------------------------------------------------------------------- /src/_shims/manual-types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | /** 5 | * Types will get added to this namespace when you import one of the following: 6 | * 7 | * import '@mux/mux-node/shims/node' 8 | * import '@mux/mux-node/shims/web' 9 | * 10 | * Importing more than one will cause type and runtime errors. 11 | */ 12 | export namespace manual {} 13 | -------------------------------------------------------------------------------- /src/_shims/manual-types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/manual-types.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/node-runtime.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import * as nf from 'node-fetch'; 5 | import * as fd from 'formdata-node'; 6 | import { type File, type FilePropertyBag } from 'formdata-node'; 7 | import KeepAliveAgent from 'agentkeepalive'; 8 | import { AbortController as AbortControllerPolyfill } from 'abort-controller'; 9 | import { ReadStream as FsReadStream } from 'node:fs'; 10 | import { type Agent } from 'node:http'; 11 | import { FormDataEncoder } from 'form-data-encoder'; 12 | import { Readable } from 'node:stream'; 13 | import { type RequestOptions } from '../core'; 14 | import { MultipartBody } from './MultipartBody'; 15 | import { type Shims } from './registry'; 16 | import { ReadableStream } from 'node:stream/web'; 17 | 18 | type FileFromPathOptions = Omit; 19 | 20 | let fileFromPathWarned = false; 21 | 22 | /** 23 | * @deprecated use fs.createReadStream('./my/file.txt') instead 24 | */ 25 | async function fileFromPath(path: string): Promise; 26 | async function fileFromPath(path: string, filename?: string): Promise; 27 | async function fileFromPath(path: string, options?: FileFromPathOptions): Promise; 28 | async function fileFromPath(path: string, filename?: string, options?: FileFromPathOptions): Promise; 29 | async function fileFromPath(path: string, ...args: any[]): Promise { 30 | // this import fails in environments that don't handle export maps correctly, like old versions of Jest 31 | const { fileFromPath: _fileFromPath } = await import('formdata-node/file-from-path'); 32 | 33 | if (!fileFromPathWarned) { 34 | console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path)}) instead`); 35 | fileFromPathWarned = true; 36 | } 37 | // @ts-ignore 38 | return await _fileFromPath(path, ...args); 39 | } 40 | 41 | const defaultHttpAgent: Agent = new KeepAliveAgent({ keepAlive: true, timeout: 5 * 60 * 1000 }); 42 | const defaultHttpsAgent: Agent = new KeepAliveAgent.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1000 }); 43 | 44 | async function getMultipartRequestOptions>( 45 | form: fd.FormData, 46 | opts: RequestOptions, 47 | ): Promise> { 48 | const encoder = new FormDataEncoder(form); 49 | const readable = Readable.from(encoder); 50 | const body = new MultipartBody(readable); 51 | const headers = { 52 | ...opts.headers, 53 | ...encoder.headers, 54 | 'Content-Length': encoder.contentLength, 55 | }; 56 | 57 | return { ...opts, body: body as any, headers }; 58 | } 59 | 60 | export function getRuntime(): Shims { 61 | // Polyfill global object if needed. 62 | if (typeof AbortController === 'undefined') { 63 | // @ts-expect-error (the types are subtly different, but compatible in practice) 64 | globalThis.AbortController = AbortControllerPolyfill; 65 | } 66 | return { 67 | kind: 'node', 68 | fetch: nf.default, 69 | Request: nf.Request, 70 | Response: nf.Response, 71 | Headers: nf.Headers, 72 | FormData: fd.FormData, 73 | Blob: fd.Blob, 74 | File: fd.File, 75 | ReadableStream, 76 | getMultipartRequestOptions, 77 | getDefaultAgent: (url: string): Agent => (url.startsWith('https') ? defaultHttpsAgent : defaultHttpAgent), 78 | fileFromPath, 79 | isFsReadStream: (value: any): value is FsReadStream => value instanceof FsReadStream, 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /src/_shims/node-types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import * as nf from 'node-fetch'; 5 | import * as fd from 'formdata-node'; 6 | 7 | export { type Agent } from 'node:http'; 8 | export { type Readable } from 'node:stream'; 9 | export { type ReadStream as FsReadStream } from 'node:fs'; 10 | export { ReadableStream } from 'node:stream/web'; 11 | 12 | export const fetch: typeof nf.default; 13 | 14 | export type Request = nf.Request; 15 | export type RequestInfo = nf.RequestInfo; 16 | export type RequestInit = nf.RequestInit; 17 | 18 | export type Response = nf.Response; 19 | export type ResponseInit = nf.ResponseInit; 20 | export type ResponseType = nf.ResponseType; 21 | export type BodyInit = nf.BodyInit; 22 | export type Headers = nf.Headers; 23 | export type HeadersInit = nf.HeadersInit; 24 | 25 | type EndingType = 'native' | 'transparent'; 26 | export interface BlobPropertyBag { 27 | endings?: EndingType; 28 | type?: string; 29 | } 30 | 31 | export interface FilePropertyBag extends BlobPropertyBag { 32 | lastModified?: number; 33 | } 34 | 35 | export type FileFromPathOptions = Omit; 36 | 37 | export type FormData = fd.FormData; 38 | export const FormData: typeof fd.FormData; 39 | export type File = fd.File; 40 | export const File: typeof fd.File; 41 | export type Blob = fd.Blob; 42 | export const Blob: typeof fd.Blob; 43 | -------------------------------------------------------------------------------- /src/_shims/node-types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/node-types.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/registry.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import { type RequestOptions } from '../core'; 5 | 6 | export interface Shims { 7 | kind: string; 8 | fetch: any; 9 | Request: any; 10 | Response: any; 11 | Headers: any; 12 | FormData: any; 13 | Blob: any; 14 | File: any; 15 | ReadableStream: any; 16 | getMultipartRequestOptions: >( 17 | form: Shims['FormData'], 18 | opts: RequestOptions, 19 | ) => Promise>; 20 | getDefaultAgent: (url: string) => any; 21 | fileFromPath: 22 | | ((path: string, filename?: string, options?: {}) => Promise) 23 | | ((path: string, options?: {}) => Promise); 24 | isFsReadStream: (value: any) => boolean; 25 | } 26 | 27 | export let auto = false; 28 | export let kind: Shims['kind'] | undefined = undefined; 29 | export let fetch: Shims['fetch'] | undefined = undefined; 30 | export let Request: Shims['Request'] | undefined = undefined; 31 | export let Response: Shims['Response'] | undefined = undefined; 32 | export let Headers: Shims['Headers'] | undefined = undefined; 33 | export let FormData: Shims['FormData'] | undefined = undefined; 34 | export let Blob: Shims['Blob'] | undefined = undefined; 35 | export let File: Shims['File'] | undefined = undefined; 36 | export let ReadableStream: Shims['ReadableStream'] | undefined = undefined; 37 | export let getMultipartRequestOptions: Shims['getMultipartRequestOptions'] | undefined = undefined; 38 | export let getDefaultAgent: Shims['getDefaultAgent'] | undefined = undefined; 39 | export let fileFromPath: Shims['fileFromPath'] | undefined = undefined; 40 | export let isFsReadStream: Shims['isFsReadStream'] | undefined = undefined; 41 | 42 | export function setShims(shims: Shims, options: { auto: boolean } = { auto: false }) { 43 | if (auto) { 44 | throw new Error( 45 | `you must \`import '@mux/mux-node/shims/${shims.kind}'\` before importing anything else from @mux/mux-node`, 46 | ); 47 | } 48 | if (kind) { 49 | throw new Error( 50 | `can't \`import '@mux/mux-node/shims/${shims.kind}'\` after \`import '@mux/mux-node/shims/${kind}'\``, 51 | ); 52 | } 53 | auto = options.auto; 54 | kind = shims.kind; 55 | fetch = shims.fetch; 56 | Request = shims.Request; 57 | Response = shims.Response; 58 | Headers = shims.Headers; 59 | FormData = shims.FormData; 60 | Blob = shims.Blob; 61 | File = shims.File; 62 | ReadableStream = shims.ReadableStream; 63 | getMultipartRequestOptions = shims.getMultipartRequestOptions; 64 | getDefaultAgent = shims.getDefaultAgent; 65 | fileFromPath = shims.fileFromPath; 66 | isFsReadStream = shims.isFsReadStream; 67 | } 68 | -------------------------------------------------------------------------------- /src/_shims/web-runtime.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import { MultipartBody } from './MultipartBody'; 5 | import { type RequestOptions } from '../core'; 6 | import { type Shims } from './registry'; 7 | 8 | export function getRuntime({ manuallyImported }: { manuallyImported?: boolean } = {}): Shims { 9 | const recommendation = 10 | manuallyImported ? 11 | `You may need to use polyfills` 12 | : `Add one of these imports before your first \`import … from '@mux/mux-node'\`: 13 | - \`import '@mux/mux-node/shims/node'\` (if you're running on Node) 14 | - \`import '@mux/mux-node/shims/web'\` (otherwise) 15 | `; 16 | 17 | let _fetch, _Request, _Response, _Headers; 18 | try { 19 | // @ts-ignore 20 | _fetch = fetch; 21 | // @ts-ignore 22 | _Request = Request; 23 | // @ts-ignore 24 | _Response = Response; 25 | // @ts-ignore 26 | _Headers = Headers; 27 | } catch (error) { 28 | throw new Error( 29 | `this environment is missing the following Web Fetch API type: ${ 30 | (error as any).message 31 | }. ${recommendation}`, 32 | ); 33 | } 34 | 35 | return { 36 | kind: 'web', 37 | fetch: _fetch, 38 | Request: _Request, 39 | Response: _Response, 40 | Headers: _Headers, 41 | FormData: 42 | // @ts-ignore 43 | typeof FormData !== 'undefined' ? FormData : ( 44 | class FormData { 45 | // @ts-ignore 46 | constructor() { 47 | throw new Error( 48 | `file uploads aren't supported in this environment yet as 'FormData' is undefined. ${recommendation}`, 49 | ); 50 | } 51 | } 52 | ), 53 | Blob: 54 | typeof Blob !== 'undefined' ? Blob : ( 55 | class Blob { 56 | constructor() { 57 | throw new Error( 58 | `file uploads aren't supported in this environment yet as 'Blob' is undefined. ${recommendation}`, 59 | ); 60 | } 61 | } 62 | ), 63 | File: 64 | // @ts-ignore 65 | typeof File !== 'undefined' ? File : ( 66 | class File { 67 | // @ts-ignore 68 | constructor() { 69 | throw new Error( 70 | `file uploads aren't supported in this environment yet as 'File' is undefined. ${recommendation}`, 71 | ); 72 | } 73 | } 74 | ), 75 | ReadableStream: 76 | // @ts-ignore 77 | typeof ReadableStream !== 'undefined' ? ReadableStream : ( 78 | class ReadableStream { 79 | // @ts-ignore 80 | constructor() { 81 | throw new Error( 82 | `streaming isn't supported in this environment yet as 'ReadableStream' is undefined. ${recommendation}`, 83 | ); 84 | } 85 | } 86 | ), 87 | getMultipartRequestOptions: async >( 88 | // @ts-ignore 89 | form: FormData, 90 | opts: RequestOptions, 91 | ): Promise> => ({ 92 | ...opts, 93 | body: new MultipartBody(form) as any, 94 | }), 95 | getDefaultAgent: (url: string) => undefined, 96 | fileFromPath: () => { 97 | throw new Error( 98 | 'The `fileFromPath` function is only supported in Node. See the README for more details: https://www.github.com/muxinc/mux-node-sdk#file-uploads', 99 | ); 100 | }, 101 | isFsReadStream: (value: any) => false, 102 | }; 103 | } 104 | -------------------------------------------------------------------------------- /src/_shims/web-types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export type Agent = any; 5 | 6 | declare const _fetch: typeof fetch; 7 | export { _fetch as fetch }; 8 | 9 | type _Request = Request; 10 | export { _Request as Request }; 11 | 12 | type _RequestInfo = RequestInfo; 13 | export { type _RequestInfo as RequestInfo }; 14 | 15 | type _RequestInit = RequestInit; 16 | export { type _RequestInit as RequestInit }; 17 | 18 | type _Response = Response; 19 | export { _Response as Response }; 20 | 21 | type _ResponseInit = ResponseInit; 22 | export { type _ResponseInit as ResponseInit }; 23 | 24 | type _ResponseType = ResponseType; 25 | export { type _ResponseType as ResponseType }; 26 | 27 | type _BodyInit = BodyInit; 28 | export { type _BodyInit as BodyInit }; 29 | 30 | type _Headers = Headers; 31 | export { _Headers as Headers }; 32 | 33 | type _HeadersInit = HeadersInit; 34 | export { type _HeadersInit as HeadersInit }; 35 | 36 | type EndingType = 'native' | 'transparent'; 37 | 38 | export interface BlobPropertyBag { 39 | endings?: EndingType; 40 | type?: string; 41 | } 42 | 43 | export interface FilePropertyBag extends BlobPropertyBag { 44 | lastModified?: number; 45 | } 46 | 47 | export type FileFromPathOptions = Omit; 48 | 49 | type _FormData = FormData; 50 | declare const _FormData: typeof FormData; 51 | export { _FormData as FormData }; 52 | 53 | type _File = File; 54 | declare const _File: typeof File; 55 | export { _File as File }; 56 | 57 | type _Blob = Blob; 58 | declare const _Blob: typeof Blob; 59 | export { _Blob as Blob }; 60 | 61 | export declare class Readable { 62 | readable: boolean; 63 | readonly readableEnded: boolean; 64 | readonly readableFlowing: boolean | null; 65 | readonly readableHighWaterMark: number; 66 | readonly readableLength: number; 67 | readonly readableObjectMode: boolean; 68 | destroyed: boolean; 69 | read(size?: number): any; 70 | pause(): this; 71 | resume(): this; 72 | isPaused(): boolean; 73 | destroy(error?: Error): this; 74 | [Symbol.asyncIterator](): AsyncIterableIterator; 75 | } 76 | 77 | export declare class FsReadStream extends Readable { 78 | path: {}; // node type is string | Buffer 79 | } 80 | 81 | type _ReadableStream = ReadableStream; 82 | declare const _ReadableStream: typeof ReadableStream; 83 | export { _ReadableStream as ReadableStream }; 84 | -------------------------------------------------------------------------------- /src/_shims/web-types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/web-types.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/error.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { castToError, Headers } from './core'; 4 | 5 | export class MuxError extends Error {} 6 | 7 | export class APIError< 8 | TStatus extends number | undefined = number | undefined, 9 | THeaders extends Headers | undefined = Headers | undefined, 10 | TError extends Object | undefined = Object | undefined, 11 | > extends MuxError { 12 | /** HTTP status for the response that caused the error */ 13 | readonly status: TStatus; 14 | /** HTTP headers for the response that caused the error */ 15 | readonly headers: THeaders; 16 | /** JSON body of the response that caused the error */ 17 | readonly error: TError; 18 | 19 | constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders) { 20 | super(`${APIError.makeMessage(status, error, message)}`); 21 | this.status = status; 22 | this.headers = headers; 23 | this.error = error; 24 | } 25 | 26 | private static makeMessage(status: number | undefined, error: any, message: string | undefined) { 27 | const msg = 28 | error?.message ? 29 | typeof error.message === 'string' ? 30 | error.message 31 | : JSON.stringify(error.message) 32 | : error ? JSON.stringify(error) 33 | : message; 34 | 35 | if (status && msg) { 36 | return `${status} ${msg}`; 37 | } 38 | if (status) { 39 | return `${status} status code (no body)`; 40 | } 41 | if (msg) { 42 | return msg; 43 | } 44 | return '(no status code or body)'; 45 | } 46 | 47 | static generate( 48 | status: number | undefined, 49 | errorResponse: Object | undefined, 50 | message: string | undefined, 51 | headers: Headers | undefined, 52 | ): APIError { 53 | if (!status || !headers) { 54 | return new APIConnectionError({ message, cause: castToError(errorResponse) }); 55 | } 56 | 57 | const error = errorResponse as Record; 58 | 59 | if (status === 400) { 60 | return new BadRequestError(status, error, message, headers); 61 | } 62 | 63 | if (status === 401) { 64 | return new AuthenticationError(status, error, message, headers); 65 | } 66 | 67 | if (status === 403) { 68 | return new PermissionDeniedError(status, error, message, headers); 69 | } 70 | 71 | if (status === 404) { 72 | return new NotFoundError(status, error, message, headers); 73 | } 74 | 75 | if (status === 409) { 76 | return new ConflictError(status, error, message, headers); 77 | } 78 | 79 | if (status === 422) { 80 | return new UnprocessableEntityError(status, error, message, headers); 81 | } 82 | 83 | if (status === 429) { 84 | return new RateLimitError(status, error, message, headers); 85 | } 86 | 87 | if (status >= 500) { 88 | return new InternalServerError(status, error, message, headers); 89 | } 90 | 91 | return new APIError(status, error, message, headers); 92 | } 93 | } 94 | 95 | export class APIUserAbortError extends APIError { 96 | constructor({ message }: { message?: string } = {}) { 97 | super(undefined, undefined, message || 'Request was aborted.', undefined); 98 | } 99 | } 100 | 101 | export class APIConnectionError extends APIError { 102 | constructor({ message, cause }: { message?: string | undefined; cause?: Error | undefined }) { 103 | super(undefined, undefined, message || 'Connection error.', undefined); 104 | // in some environments the 'cause' property is already declared 105 | // @ts-ignore 106 | if (cause) this.cause = cause; 107 | } 108 | } 109 | 110 | export class APIConnectionTimeoutError extends APIConnectionError { 111 | constructor({ message }: { message?: string } = {}) { 112 | super({ message: message ?? 'Request timed out.' }); 113 | } 114 | } 115 | 116 | export class BadRequestError extends APIError<400, Headers> {} 117 | 118 | export class AuthenticationError extends APIError<401, Headers> {} 119 | 120 | export class PermissionDeniedError extends APIError<403, Headers> {} 121 | 122 | export class NotFoundError extends APIError<404, Headers> {} 123 | 124 | export class ConflictError extends APIError<409, Headers> {} 125 | 126 | export class UnprocessableEntityError extends APIError<422, Headers> {} 127 | 128 | export class RateLimitError extends APIError<429, Headers> {} 129 | 130 | export class InternalServerError extends APIError {} 131 | -------------------------------------------------------------------------------- /src/internal/qs/LICENSE.md: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/puruvj/neoqs/graphs/contributors) All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | -------------------------------------------------------------------------------- /src/internal/qs/README.md: -------------------------------------------------------------------------------- 1 | # qs 2 | 3 | This is a vendored version of [neoqs](https://github.com/PuruVJ/neoqs) which is a TypeScript rewrite of [qs](https://github.com/ljharb/qs), a query string library. 4 | -------------------------------------------------------------------------------- /src/internal/qs/formats.ts: -------------------------------------------------------------------------------- 1 | import type { Format } from './types'; 2 | 3 | export const default_format: Format = 'RFC3986'; 4 | export const formatters: Record string> = { 5 | RFC1738: (v: PropertyKey) => String(v).replace(/%20/g, '+'), 6 | RFC3986: (v: PropertyKey) => String(v), 7 | }; 8 | export const RFC1738 = 'RFC1738'; 9 | export const RFC3986 = 'RFC3986'; 10 | -------------------------------------------------------------------------------- /src/internal/qs/index.ts: -------------------------------------------------------------------------------- 1 | import { default_format, formatters, RFC1738, RFC3986 } from './formats'; 2 | 3 | const formats = { 4 | formatters, 5 | RFC1738, 6 | RFC3986, 7 | default: default_format, 8 | }; 9 | 10 | export { stringify } from './stringify'; 11 | export { formats }; 12 | 13 | export type { DefaultDecoder, DefaultEncoder, Format, ParseOptions, StringifyOptions } from './types'; 14 | -------------------------------------------------------------------------------- /src/internal/qs/types.ts: -------------------------------------------------------------------------------- 1 | export type Format = 'RFC1738' | 'RFC3986'; 2 | 3 | export type DefaultEncoder = (str: any, defaultEncoder?: any, charset?: string) => string; 4 | export type DefaultDecoder = (str: string, decoder?: any, charset?: string) => string; 5 | 6 | export type BooleanOptional = boolean | undefined; 7 | 8 | export type StringifyBaseOptions = { 9 | delimiter?: string; 10 | allowDots?: boolean; 11 | encodeDotInKeys?: boolean; 12 | strictNullHandling?: boolean; 13 | skipNulls?: boolean; 14 | encode?: boolean; 15 | encoder?: ( 16 | str: any, 17 | defaultEncoder: DefaultEncoder, 18 | charset: string, 19 | type: 'key' | 'value', 20 | format?: Format, 21 | ) => string; 22 | filter?: Array | ((prefix: PropertyKey, value: any) => any); 23 | arrayFormat?: 'indices' | 'brackets' | 'repeat' | 'comma'; 24 | indices?: boolean; 25 | sort?: ((a: PropertyKey, b: PropertyKey) => number) | null; 26 | serializeDate?: (d: Date) => string; 27 | format?: 'RFC1738' | 'RFC3986'; 28 | formatter?: (str: PropertyKey) => string; 29 | encodeValuesOnly?: boolean; 30 | addQueryPrefix?: boolean; 31 | charset?: 'utf-8' | 'iso-8859-1'; 32 | charsetSentinel?: boolean; 33 | allowEmptyArrays?: boolean; 34 | commaRoundTrip?: boolean; 35 | }; 36 | 37 | export type StringifyOptions = StringifyBaseOptions; 38 | 39 | export type ParseBaseOptions = { 40 | comma?: boolean; 41 | delimiter?: string | RegExp; 42 | depth?: number | false; 43 | decoder?: (str: string, defaultDecoder: DefaultDecoder, charset: string, type: 'key' | 'value') => any; 44 | arrayLimit?: number; 45 | parseArrays?: boolean; 46 | plainObjects?: boolean; 47 | allowPrototypes?: boolean; 48 | allowSparse?: boolean; 49 | parameterLimit?: number; 50 | strictDepth?: boolean; 51 | strictNullHandling?: boolean; 52 | ignoreQueryPrefix?: boolean; 53 | charset?: 'utf-8' | 'iso-8859-1'; 54 | charsetSentinel?: boolean; 55 | interpretNumericEntities?: boolean; 56 | allowEmptyArrays?: boolean; 57 | duplicates?: 'combine' | 'first' | 'last'; 58 | allowDots?: boolean; 59 | decodeDotInKeys?: boolean; 60 | }; 61 | 62 | export type ParseOptions = ParseBaseOptions; 63 | 64 | export type ParsedQs = { 65 | [key: string]: undefined | string | string[] | ParsedQs | ParsedQs[]; 66 | }; 67 | 68 | // Type to remove null or undefined union from each property 69 | export type NonNullableProperties = { 70 | [K in keyof T]-?: Exclude; 71 | }; 72 | -------------------------------------------------------------------------------- /src/lib/.keep: -------------------------------------------------------------------------------- 1 | File generated from our OpenAPI spec by Stainless. 2 | 3 | This directory can be used to store custom files to expand the SDK. 4 | It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. 5 | -------------------------------------------------------------------------------- /src/pagination.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { AbstractPage, Response, APIClient, FinalRequestOptions, PageInfo } from './core'; 4 | 5 | export interface PageWithTotalResponse { 6 | data: Array; 7 | 8 | total_row_count: number; 9 | 10 | timeframe: Array; 11 | 12 | /** 13 | * Number of assets returned in this response. Default value is 100. 14 | */ 15 | limit: number; 16 | } 17 | 18 | export interface PageWithTotalParams { 19 | page?: number; 20 | 21 | limit?: number; 22 | } 23 | 24 | export class PageWithTotal extends AbstractPage implements PageWithTotalResponse { 25 | data: Array; 26 | 27 | total_row_count: number; 28 | 29 | timeframe: Array; 30 | 31 | /** 32 | * Number of assets returned in this response. Default value is 100. 33 | */ 34 | limit: number; 35 | 36 | constructor( 37 | client: APIClient, 38 | response: Response, 39 | body: PageWithTotalResponse, 40 | options: FinalRequestOptions, 41 | ) { 42 | super(client, response, body, options); 43 | 44 | this.data = body.data || []; 45 | this.total_row_count = body.total_row_count || 0; 46 | this.timeframe = body.timeframe || []; 47 | this.limit = body.limit || 0; 48 | } 49 | 50 | getPaginatedItems(): Item[] { 51 | return this.data ?? []; 52 | } 53 | 54 | // @deprecated Please use `nextPageInfo()` instead 55 | nextPageParams(): Partial | null { 56 | const info = this.nextPageInfo(); 57 | if (!info) return null; 58 | if ('params' in info) return info.params; 59 | const params = Object.fromEntries(info.url.searchParams); 60 | if (!Object.keys(params).length) return null; 61 | return params; 62 | } 63 | 64 | nextPageInfo(): PageInfo | null { 65 | const query = this.options.query as PageWithTotalParams; 66 | const currentPage = query?.page ?? 1; 67 | 68 | return { params: { page: currentPage + 1 } }; 69 | } 70 | } 71 | 72 | export interface BasePageResponse { 73 | data: Array; 74 | } 75 | 76 | export interface BasePageParams { 77 | page?: number; 78 | 79 | limit?: number; 80 | } 81 | 82 | export class BasePage extends AbstractPage implements BasePageResponse { 83 | data: Array; 84 | 85 | constructor( 86 | client: APIClient, 87 | response: Response, 88 | body: BasePageResponse, 89 | options: FinalRequestOptions, 90 | ) { 91 | super(client, response, body, options); 92 | 93 | this.data = body.data || []; 94 | } 95 | 96 | getPaginatedItems(): Item[] { 97 | return this.data ?? []; 98 | } 99 | 100 | // @deprecated Please use `nextPageInfo()` instead 101 | nextPageParams(): Partial | null { 102 | const info = this.nextPageInfo(); 103 | if (!info) return null; 104 | if ('params' in info) return info.params; 105 | const params = Object.fromEntries(info.url.searchParams); 106 | if (!Object.keys(params).length) return null; 107 | return params; 108 | } 109 | 110 | nextPageInfo(): PageInfo | null { 111 | const query = this.options.query as BasePageParams; 112 | const currentPage = query?.page ?? 1; 113 | 114 | return { params: { page: currentPage + 1 } }; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/resource.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import type { Mux } from './index'; 4 | 5 | export class APIResource { 6 | protected _client: Mux; 7 | 8 | constructor(client: Mux) { 9 | this._client = client; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/resources.ts: -------------------------------------------------------------------------------- 1 | export * from './resources/index'; 2 | -------------------------------------------------------------------------------- /src/resources/data.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './data/index'; 4 | -------------------------------------------------------------------------------- /src/resources/data/dimensions.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import { isRequestOptions } from '../../core'; 5 | import * as Core from '../../core'; 6 | import { BasePage, type BasePageParams } from '../../pagination'; 7 | 8 | export class Dimensions extends APIResource { 9 | /** 10 | * List all available dimensions. 11 | * 12 | * Note: This API replaces the list-filters API call. 13 | * 14 | * @example 15 | * ```ts 16 | * const dimensionsResponse = 17 | * await client.data.dimensions.list(); 18 | * ``` 19 | */ 20 | list(options?: Core.RequestOptions): Core.APIPromise { 21 | return this._client.get('/data/v1/dimensions', options); 22 | } 23 | 24 | /** 25 | * Lists the values for a dimension along with a total count of related views. 26 | * 27 | * Note: This API replaces the list-filter-values API call. 28 | * 29 | * @example 30 | * ```ts 31 | * // Automatically fetches more pages as needed. 32 | * for await (const dimensionValue of client.data.dimensions.listValues( 33 | * 'abcd1234', 34 | * )) { 35 | * // ... 36 | * } 37 | * ``` 38 | */ 39 | listValues( 40 | dimensionId: string, 41 | query?: DimensionListValuesParams, 42 | options?: Core.RequestOptions, 43 | ): Core.PagePromise; 44 | listValues( 45 | dimensionId: string, 46 | options?: Core.RequestOptions, 47 | ): Core.PagePromise; 48 | listValues( 49 | dimensionId: string, 50 | query: DimensionListValuesParams | Core.RequestOptions = {}, 51 | options?: Core.RequestOptions, 52 | ): Core.PagePromise { 53 | if (isRequestOptions(query)) { 54 | return this.listValues(dimensionId, {}, query); 55 | } 56 | return this._client.getAPIList(`/data/v1/dimensions/${dimensionId}`, DimensionValuesBasePage, { 57 | query, 58 | ...options, 59 | }); 60 | } 61 | } 62 | 63 | export class DimensionValuesBasePage extends BasePage {} 64 | 65 | export interface DimensionValue { 66 | total_count: number; 67 | 68 | value: string | null; 69 | } 70 | 71 | export interface DimensionsResponse { 72 | data: DimensionsResponse.Data; 73 | 74 | timeframe: Array; 75 | 76 | total_row_count: number | null; 77 | } 78 | 79 | export namespace DimensionsResponse { 80 | export interface Data { 81 | advanced: Array; 82 | 83 | basic: Array; 84 | } 85 | } 86 | 87 | export interface DimensionListValuesParams extends BasePageParams { 88 | /** 89 | * Limit the results to rows that match conditions from provided key:value pairs. 90 | * Must be provided as an array query string parameter. 91 | * 92 | * To exclude rows that match a certain condition, prepend a `!` character to the 93 | * dimension. 94 | * 95 | * Possible filter names are the same as returned by the List Filters endpoint. 96 | * 97 | * Example: 98 | * 99 | * - `filters[]=operating_system:windows&filters[]=!country:US` 100 | */ 101 | filters?: Array; 102 | 103 | /** 104 | * Limit the results to rows that match inequality conditions from provided metric 105 | * comparison clauses. Must be provided as an array query string parameter. 106 | * 107 | * Possible filterable metrics are the same as the set of metric ids, with the 108 | * exceptions of `exits_before_video_start`, `unique_viewers`, 109 | * `video_startup_failure_percentage`, `view_dropped_percentage`, and `views`. 110 | * 111 | * Example: 112 | * 113 | * - `metric_filters[]=aggregate_startup_time>=1000` 114 | */ 115 | metric_filters?: Array; 116 | 117 | /** 118 | * Timeframe window to limit results by. Must be provided as an array query string 119 | * parameter (e.g. timeframe[]=). 120 | * 121 | * Accepted formats are... 122 | * 123 | * - array of epoch timestamps e.g. `timeframe[]=1498867200&timeframe[]=1498953600` 124 | * - duration string e.g. `timeframe[]=24:hours or timeframe[]=7:days` 125 | */ 126 | timeframe?: Array; 127 | } 128 | 129 | Dimensions.DimensionValuesBasePage = DimensionValuesBasePage; 130 | 131 | export declare namespace Dimensions { 132 | export { 133 | type DimensionValue as DimensionValue, 134 | type DimensionsResponse as DimensionsResponse, 135 | DimensionValuesBasePage as DimensionValuesBasePage, 136 | type DimensionListValuesParams as DimensionListValuesParams, 137 | }; 138 | } 139 | -------------------------------------------------------------------------------- /src/resources/data/errors.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import { isRequestOptions } from '../../core'; 5 | import * as Core from '../../core'; 6 | 7 | export class Errors extends APIResource { 8 | /** 9 | * Returns a list of errors. 10 | * 11 | * @example 12 | * ```ts 13 | * const errorsResponse = await client.data.errors.list(); 14 | * ``` 15 | */ 16 | list(query?: ErrorListParams, options?: Core.RequestOptions): Core.APIPromise; 17 | list(options?: Core.RequestOptions): Core.APIPromise; 18 | list( 19 | query: ErrorListParams | Core.RequestOptions = {}, 20 | options?: Core.RequestOptions, 21 | ): Core.APIPromise { 22 | if (isRequestOptions(query)) { 23 | return this.list({}, query); 24 | } 25 | return this._client.get('/data/v1/errors', { query, ...options }); 26 | } 27 | } 28 | 29 | export interface ErrorsResponse { 30 | data: Array; 31 | 32 | timeframe: Array; 33 | 34 | total_row_count: number | null; 35 | } 36 | 37 | export namespace ErrorsResponse { 38 | export interface Data { 39 | /** 40 | * A unique identifier for this error. 41 | */ 42 | id: number; 43 | 44 | /** 45 | * The error code 46 | */ 47 | code: number | null; 48 | 49 | /** 50 | * The total number of views that experienced this error. 51 | */ 52 | count: number; 53 | 54 | /** 55 | * Description of the error. 56 | */ 57 | description: string | null; 58 | 59 | /** 60 | * The last time this error was seen (ISO 8601 timestamp). 61 | */ 62 | last_seen: string; 63 | 64 | /** 65 | * The error message. 66 | */ 67 | message: string | null; 68 | 69 | /** 70 | * Notes that are attached to this error. 71 | */ 72 | notes: string | null; 73 | 74 | /** 75 | * The percentage of views that experienced this error. 76 | */ 77 | percentage: number; 78 | 79 | /** 80 | * The string version of the error code 81 | */ 82 | player_error_code: string | null; 83 | } 84 | } 85 | 86 | export interface ErrorListParams { 87 | /** 88 | * Limit the results to rows that match conditions from provided key:value pairs. 89 | * Must be provided as an array query string parameter. 90 | * 91 | * To exclude rows that match a certain condition, prepend a `!` character to the 92 | * dimension. 93 | * 94 | * Possible filter names are the same as returned by the List Filters endpoint. 95 | * 96 | * Example: 97 | * 98 | * - `filters[]=operating_system:windows&filters[]=!country:US` 99 | */ 100 | filters?: Array; 101 | 102 | /** 103 | * Limit the results to rows that match inequality conditions from provided metric 104 | * comparison clauses. Must be provided as an array query string parameter. 105 | * 106 | * Possible filterable metrics are the same as the set of metric ids, with the 107 | * exceptions of `exits_before_video_start`, `unique_viewers`, 108 | * `video_startup_failure_percentage`, `view_dropped_percentage`, and `views`. 109 | * 110 | * Example: 111 | * 112 | * - `metric_filters[]=aggregate_startup_time>=1000` 113 | */ 114 | metric_filters?: Array; 115 | 116 | /** 117 | * Timeframe window to limit results by. Must be provided as an array query string 118 | * parameter (e.g. timeframe[]=). 119 | * 120 | * Accepted formats are... 121 | * 122 | * - array of epoch timestamps e.g. `timeframe[]=1498867200&timeframe[]=1498953600` 123 | * - duration string e.g. `timeframe[]=24:hours or timeframe[]=7:days` 124 | */ 125 | timeframe?: Array; 126 | } 127 | 128 | export declare namespace Errors { 129 | export { type ErrorsResponse as ErrorsResponse, type ErrorListParams as ErrorListParams }; 130 | } 131 | -------------------------------------------------------------------------------- /src/resources/data/exports.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import * as Core from '../../core'; 5 | 6 | export class Exports extends APIResource { 7 | /** 8 | * Lists the available video view exports along with URLs to retrieve them. 9 | * 10 | * @example 11 | * ```ts 12 | * const videoViewExportsResponse = 13 | * await client.data.exports.listVideoViews(); 14 | * ``` 15 | */ 16 | listVideoViews(options?: Core.RequestOptions): Core.APIPromise { 17 | return this._client.get('/data/v1/exports/views', options); 18 | } 19 | } 20 | 21 | export interface ExportsResponse { 22 | data: Array; 23 | 24 | timeframe: Array; 25 | 26 | total_row_count: number | null; 27 | } 28 | 29 | export interface VideoViewExportsResponse { 30 | data: Array; 31 | 32 | timeframe: Array; 33 | 34 | total_row_count: number | null; 35 | } 36 | 37 | export namespace VideoViewExportsResponse { 38 | export interface Data { 39 | export_date: string; 40 | 41 | files: Array; 42 | } 43 | 44 | export namespace Data { 45 | export interface File { 46 | path: string; 47 | 48 | type: string; 49 | 50 | version: number; 51 | } 52 | } 53 | } 54 | 55 | export declare namespace Exports { 56 | export { 57 | type ExportsResponse as ExportsResponse, 58 | type VideoViewExportsResponse as VideoViewExportsResponse, 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /src/resources/data/filters.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import { isRequestOptions } from '../../core'; 5 | import * as Core from '../../core'; 6 | import { BasePage, type BasePageParams } from '../../pagination'; 7 | 8 | export class Filters extends APIResource { 9 | /** 10 | * The API has been replaced by the list-dimension-values API call. 11 | * 12 | * Lists the values for a filter along with a total count of related views. 13 | * 14 | * @example 15 | * ```ts 16 | * // Automatically fetches more pages as needed. 17 | * for await (const filterValue of client.data.filters.listValues( 18 | * 'abcd1234', 19 | * )) { 20 | * // ... 21 | * } 22 | * ``` 23 | */ 24 | listValues( 25 | filterId: string, 26 | query?: FilterListValuesParams, 27 | options?: Core.RequestOptions, 28 | ): Core.PagePromise; 29 | listValues( 30 | filterId: string, 31 | options?: Core.RequestOptions, 32 | ): Core.PagePromise; 33 | listValues( 34 | filterId: string, 35 | query: FilterListValuesParams | Core.RequestOptions = {}, 36 | options?: Core.RequestOptions, 37 | ): Core.PagePromise { 38 | if (isRequestOptions(query)) { 39 | return this.listValues(filterId, {}, query); 40 | } 41 | return this._client.getAPIList(`/data/v1/filters/${filterId}`, FilterValuesBasePage, { 42 | query, 43 | ...options, 44 | }); 45 | } 46 | } 47 | 48 | export class FilterValuesBasePage extends BasePage {} 49 | 50 | export interface FilterValue { 51 | total_count: number; 52 | 53 | value: string | null; 54 | } 55 | 56 | export interface FiltersResponse { 57 | data: FiltersResponse.Data; 58 | 59 | timeframe: Array; 60 | 61 | total_row_count: number | null; 62 | } 63 | 64 | export namespace FiltersResponse { 65 | export interface Data { 66 | advanced: Array; 67 | 68 | basic: Array; 69 | } 70 | } 71 | 72 | export interface FilterListValuesParams extends BasePageParams { 73 | /** 74 | * Limit the results to rows that match conditions from provided key:value pairs. 75 | * Must be provided as an array query string parameter. 76 | * 77 | * To exclude rows that match a certain condition, prepend a `!` character to the 78 | * dimension. 79 | * 80 | * Possible filter names are the same as returned by the List Filters endpoint. 81 | * 82 | * Example: 83 | * 84 | * - `filters[]=operating_system:windows&filters[]=!country:US` 85 | */ 86 | filters?: Array; 87 | 88 | /** 89 | * Timeframe window to limit results by. Must be provided as an array query string 90 | * parameter (e.g. timeframe[]=). 91 | * 92 | * Accepted formats are... 93 | * 94 | * - array of epoch timestamps e.g. `timeframe[]=1498867200&timeframe[]=1498953600` 95 | * - duration string e.g. `timeframe[]=24:hours or timeframe[]=7:days` 96 | */ 97 | timeframe?: Array; 98 | } 99 | 100 | Filters.FilterValuesBasePage = FilterValuesBasePage; 101 | 102 | export declare namespace Filters { 103 | export { 104 | type FilterValue as FilterValue, 105 | type FiltersResponse as FiltersResponse, 106 | FilterValuesBasePage as FilterValuesBasePage, 107 | type FilterListValuesParams as FilterListValuesParams, 108 | }; 109 | } 110 | -------------------------------------------------------------------------------- /src/resources/data/incidents.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import { isRequestOptions } from '../../core'; 5 | import * as Core from '../../core'; 6 | import { BasePage, type BasePageParams } from '../../pagination'; 7 | 8 | export class Incidents extends APIResource { 9 | /** 10 | * Returns the details of an incident. 11 | * 12 | * @example 13 | * ```ts 14 | * const incidentResponse = 15 | * await client.data.incidents.retrieve('abcd1234'); 16 | * ``` 17 | */ 18 | retrieve(incidentId: string, options?: Core.RequestOptions): Core.APIPromise { 19 | return this._client.get(`/data/v1/incidents/${incidentId}`, options); 20 | } 21 | 22 | /** 23 | * Returns a list of incidents. 24 | * 25 | * @example 26 | * ```ts 27 | * // Automatically fetches more pages as needed. 28 | * for await (const incident of client.data.incidents.list()) { 29 | * // ... 30 | * } 31 | * ``` 32 | */ 33 | list( 34 | query?: IncidentListParams, 35 | options?: Core.RequestOptions, 36 | ): Core.PagePromise; 37 | list(options?: Core.RequestOptions): Core.PagePromise; 38 | list( 39 | query: IncidentListParams | Core.RequestOptions = {}, 40 | options?: Core.RequestOptions, 41 | ): Core.PagePromise { 42 | if (isRequestOptions(query)) { 43 | return this.list({}, query); 44 | } 45 | return this._client.getAPIList('/data/v1/incidents', IncidentsBasePage, { query, ...options }); 46 | } 47 | 48 | /** 49 | * Returns all the incidents that seem related to a specific incident. 50 | * 51 | * @example 52 | * ```ts 53 | * // Automatically fetches more pages as needed. 54 | * for await (const incident of client.data.incidents.listRelated( 55 | * 'abcd1234', 56 | * )) { 57 | * // ... 58 | * } 59 | * ``` 60 | */ 61 | listRelated( 62 | incidentId: string, 63 | query?: IncidentListRelatedParams, 64 | options?: Core.RequestOptions, 65 | ): Core.PagePromise; 66 | listRelated( 67 | incidentId: string, 68 | options?: Core.RequestOptions, 69 | ): Core.PagePromise; 70 | listRelated( 71 | incidentId: string, 72 | query: IncidentListRelatedParams | Core.RequestOptions = {}, 73 | options?: Core.RequestOptions, 74 | ): Core.PagePromise { 75 | if (isRequestOptions(query)) { 76 | return this.listRelated(incidentId, {}, query); 77 | } 78 | return this._client.getAPIList(`/data/v1/incidents/${incidentId}/related`, IncidentsBasePage, { 79 | query, 80 | ...options, 81 | }); 82 | } 83 | } 84 | 85 | export class IncidentsBasePage extends BasePage {} 86 | 87 | export interface Incident { 88 | id: string; 89 | 90 | affected_views: number; 91 | 92 | affected_views_per_hour: number; 93 | 94 | affected_views_per_hour_on_open: number; 95 | 96 | breakdowns: Array; 97 | 98 | description: string; 99 | 100 | error_description: string; 101 | 102 | impact: string; 103 | 104 | incident_key: string; 105 | 106 | measured_value: number | null; 107 | 108 | measured_value_on_close: number | null; 109 | 110 | measurement: string; 111 | 112 | notification_rules: Array; 113 | 114 | notifications: Array; 115 | 116 | resolved_at: string | null; 117 | 118 | sample_size: number; 119 | 120 | sample_size_unit: string; 121 | 122 | severity: string; 123 | 124 | started_at: string; 125 | 126 | status: string; 127 | 128 | threshold: number; 129 | } 130 | 131 | export namespace Incident { 132 | export interface Breakdown { 133 | id: string; 134 | 135 | name: string; 136 | 137 | value: string; 138 | } 139 | 140 | export interface NotificationRule { 141 | id: string; 142 | 143 | action: string; 144 | 145 | property_id: string; 146 | 147 | rules: Array; 148 | 149 | status: string; 150 | } 151 | 152 | export namespace NotificationRule { 153 | export interface Rule { 154 | id: string; 155 | 156 | name: string; 157 | 158 | value: string; 159 | } 160 | } 161 | 162 | export interface Notification { 163 | id: number; 164 | 165 | attempted_at: string; 166 | 167 | queued_at: string; 168 | } 169 | } 170 | 171 | export interface IncidentResponse { 172 | data: Incident; 173 | 174 | timeframe: Array; 175 | 176 | total_row_count: number | null; 177 | } 178 | 179 | export interface IncidentListParams extends BasePageParams { 180 | /** 181 | * Value to order the results by 182 | */ 183 | order_by?: 'negative_impact' | 'value' | 'views' | 'field'; 184 | 185 | /** 186 | * Sort order. 187 | */ 188 | order_direction?: 'asc' | 'desc'; 189 | 190 | /** 191 | * Severity to filter incidents by 192 | */ 193 | severity?: 'warning' | 'alert'; 194 | 195 | /** 196 | * Status to filter incidents by 197 | */ 198 | status?: 'open' | 'closed' | 'expired'; 199 | } 200 | 201 | export interface IncidentListRelatedParams extends BasePageParams { 202 | /** 203 | * Value to order the results by 204 | */ 205 | order_by?: 'negative_impact' | 'value' | 'views' | 'field'; 206 | 207 | /** 208 | * Sort order. 209 | */ 210 | order_direction?: 'asc' | 'desc'; 211 | } 212 | 213 | Incidents.IncidentsBasePage = IncidentsBasePage; 214 | 215 | export declare namespace Incidents { 216 | export { 217 | type Incident as Incident, 218 | type IncidentResponse as IncidentResponse, 219 | IncidentsBasePage as IncidentsBasePage, 220 | type IncidentListParams as IncidentListParams, 221 | type IncidentListRelatedParams as IncidentListRelatedParams, 222 | }; 223 | } 224 | -------------------------------------------------------------------------------- /src/resources/data/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { 4 | AbridgedVideoViewsBasePage, 5 | VideoViews, 6 | type AbridgedVideoView, 7 | type VideoViewResponse, 8 | type VideoViewListParams, 9 | } from './video-views'; 10 | export { 11 | AnnotationsBasePage, 12 | Annotations, 13 | type Annotation, 14 | type AnnotationInput, 15 | type AnnotationResponse, 16 | type ListAnnotationsResponse, 17 | type AnnotationCreateParams, 18 | type AnnotationUpdateParams, 19 | type AnnotationListParams, 20 | } from './annotations'; 21 | export { 22 | BreakdownValuesBasePage, 23 | Metrics, 24 | type AllMetricValuesResponse, 25 | type BreakdownValue, 26 | type InsightsResponse, 27 | type MetricTimeseriesDataResponse, 28 | type OverallValuesResponse, 29 | type MetricListParams, 30 | type MetricGetInsightsParams, 31 | type MetricGetOverallValuesParams, 32 | type MetricGetTimeseriesParams, 33 | type MetricListBreakdownValuesParams, 34 | } from './metrics'; 35 | export { Data } from './data'; 36 | export { 37 | DimensionValuesBasePage, 38 | Dimensions, 39 | type DimensionValue, 40 | type DimensionsResponse, 41 | type DimensionListValuesParams, 42 | } from './dimensions'; 43 | export { Errors, type ErrorsResponse, type ErrorListParams } from './errors'; 44 | export { Exports, type ExportsResponse, type VideoViewExportsResponse } from './exports'; 45 | export { 46 | FilterValuesBasePage, 47 | Filters, 48 | type FilterValue, 49 | type FiltersResponse, 50 | type FilterListValuesParams, 51 | } from './filters'; 52 | export { 53 | IncidentsBasePage, 54 | Incidents, 55 | type Incident, 56 | type IncidentResponse, 57 | type IncidentListParams, 58 | type IncidentListRelatedParams, 59 | } from './incidents'; 60 | export { Monitoring, type MonitoringListDimensionsResponse } from './monitoring/index'; 61 | export { 62 | RealTime, 63 | type RealTimeBreakdownResponse, 64 | type RealTimeDimensionsResponse, 65 | type RealTimeHistogramTimeseriesResponse, 66 | type RealTimeMetricsResponse, 67 | type RealTimeTimeseriesResponse, 68 | type RealTimeRetrieveBreakdownParams, 69 | type RealTimeRetrieveHistogramTimeseriesParams, 70 | type RealTimeRetrieveTimeseriesParams, 71 | } from './real-time'; 72 | -------------------------------------------------------------------------------- /src/resources/data/monitoring.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './monitoring/index'; 4 | -------------------------------------------------------------------------------- /src/resources/data/monitoring/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { 4 | Metrics, 5 | type MetricListResponse, 6 | type MetricGetBreakdownResponse, 7 | type MetricGetBreakdownTimeseriesResponse, 8 | type MetricGetHistogramTimeseriesResponse, 9 | type MetricGetTimeseriesResponse, 10 | type MetricGetBreakdownParams, 11 | type MetricGetBreakdownTimeseriesParams, 12 | type MetricGetHistogramTimeseriesParams, 13 | type MetricGetTimeseriesParams, 14 | } from './metrics'; 15 | export { Monitoring, type MonitoringListDimensionsResponse } from './monitoring'; 16 | -------------------------------------------------------------------------------- /src/resources/data/monitoring/monitoring.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../../resource'; 4 | import * as Core from '../../../core'; 5 | import * as MetricsAPI from './metrics'; 6 | import { 7 | MetricGetBreakdownParams, 8 | MetricGetBreakdownResponse, 9 | MetricGetBreakdownTimeseriesParams, 10 | MetricGetBreakdownTimeseriesResponse, 11 | MetricGetHistogramTimeseriesParams, 12 | MetricGetHistogramTimeseriesResponse, 13 | MetricGetTimeseriesParams, 14 | MetricGetTimeseriesResponse, 15 | MetricListResponse, 16 | Metrics, 17 | } from './metrics'; 18 | 19 | export class Monitoring extends APIResource { 20 | metrics: MetricsAPI.Metrics = new MetricsAPI.Metrics(this._client); 21 | 22 | /** 23 | * Lists available monitoring dimensions. 24 | * 25 | * @example 26 | * ```ts 27 | * const response = 28 | * await client.data.monitoring.listDimensions(); 29 | * ``` 30 | */ 31 | listDimensions(options?: Core.RequestOptions): Core.APIPromise { 32 | return this._client.get('/data/v1/monitoring/dimensions', options); 33 | } 34 | } 35 | 36 | export interface MonitoringListDimensionsResponse { 37 | data: Array; 38 | 39 | timeframe: Array; 40 | 41 | total_row_count: number | null; 42 | } 43 | 44 | export namespace MonitoringListDimensionsResponse { 45 | export interface Data { 46 | display_name: string; 47 | 48 | name: string; 49 | } 50 | } 51 | 52 | Monitoring.Metrics = Metrics; 53 | 54 | export declare namespace Monitoring { 55 | export { type MonitoringListDimensionsResponse as MonitoringListDimensionsResponse }; 56 | 57 | export { 58 | Metrics as Metrics, 59 | type MetricListResponse as MetricListResponse, 60 | type MetricGetBreakdownResponse as MetricGetBreakdownResponse, 61 | type MetricGetBreakdownTimeseriesResponse as MetricGetBreakdownTimeseriesResponse, 62 | type MetricGetHistogramTimeseriesResponse as MetricGetHistogramTimeseriesResponse, 63 | type MetricGetTimeseriesResponse as MetricGetTimeseriesResponse, 64 | type MetricGetBreakdownParams as MetricGetBreakdownParams, 65 | type MetricGetBreakdownTimeseriesParams as MetricGetBreakdownTimeseriesParams, 66 | type MetricGetHistogramTimeseriesParams as MetricGetHistogramTimeseriesParams, 67 | type MetricGetTimeseriesParams as MetricGetTimeseriesParams, 68 | }; 69 | } 70 | -------------------------------------------------------------------------------- /src/resources/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './shared'; 4 | export { Data } from './data/data'; 5 | export { Jwt } from './jwt'; 6 | export { System } from './system/system'; 7 | export { Video } from './video/video'; 8 | export { Webhooks } from './webhooks'; 9 | -------------------------------------------------------------------------------- /src/resources/jwt.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. 2 | 3 | import { APIResource } from '@mux/mux-node/resource'; 4 | import * as jwt from '@mux/mux-node/_shims/auto/jwt'; 5 | import { 6 | type SignOptions, 7 | TypeClaim, 8 | DataTypeClaim, 9 | TypeToken, 10 | type MuxJWTSignOptions, 11 | type MuxJWTSignOptionsMultiple, 12 | type Tokens, 13 | isMuxJWTSignOptionsMultiple, 14 | } from '@mux/mux-node/util/jwt-types'; 15 | 16 | export class Jwt extends APIResource { 17 | async signPlaybackId( 18 | playbackId: string, 19 | config?: MuxJWTSignOptions, 20 | ): Promise; 21 | 22 | async signPlaybackId( 23 | playbackId: string, 24 | config?: MuxJWTSignOptionsMultiple, 25 | ): Promise; 26 | 27 | /** 28 | * Creates a new token or tokens to be used with a signed Playback ID 29 | */ 30 | async signPlaybackId( 31 | playbackId: string, 32 | config: 33 | | MuxJWTSignOptions 34 | | MuxJWTSignOptionsMultiple = {}, 35 | ): Promise { 36 | if (isMuxJWTSignOptionsMultiple(config)) { 37 | return this.signPlaybackIdMultipleTypes(playbackId, config); 38 | } else { 39 | return this.signPlaybackIdSingleType(playbackId, config); 40 | } 41 | } 42 | 43 | private async signPlaybackIdSingleType( 44 | playbackId: string, 45 | config: MuxJWTSignOptions, 46 | ): Promise { 47 | const claim = TypeClaim[config.type ?? 'video']; 48 | if (!claim) { 49 | throw new Error(`Invalid signature type: ${config.type}; Expected one of ${Object.keys(TypeClaim)}`); 50 | } 51 | 52 | const tokenOptions: SignOptions = { 53 | keyid: jwt.getSigningKey(this._client, config), 54 | subject: playbackId, 55 | audience: claim, 56 | expiresIn: config.expiration ?? '7d', 57 | noTimestamp: true, 58 | algorithm: 'RS256', 59 | }; 60 | 61 | return jwt.sign(config.params ?? {}, await jwt.getPrivateKey(this._client, config), tokenOptions); 62 | } 63 | 64 | private async signPlaybackIdMultipleTypes( 65 | playbackId: string, 66 | config: MuxJWTSignOptionsMultiple, 67 | ): Promise { 68 | const tokens: Tokens = {}; 69 | 70 | for (const typeOption of config.type) { 71 | let type: keyof typeof TypeClaim; 72 | let params: Record | undefined; 73 | 74 | if (Array.isArray(typeOption)) { 75 | [type, params] = typeOption; 76 | } else { 77 | type = typeOption; 78 | params = undefined; 79 | } 80 | 81 | const singleConfig = { 82 | ...config, 83 | type, 84 | params: { 85 | ...config.params, 86 | ...params, 87 | }, 88 | }; 89 | 90 | const token = await this.signPlaybackIdSingleType(playbackId, singleConfig); 91 | 92 | const tokenKey = TypeToken[type]; 93 | if (tokenKey) { 94 | tokens[tokenKey] = token; 95 | } 96 | } 97 | 98 | return tokens; 99 | } 100 | 101 | /** 102 | * Creates a new token for a license for playing back DRM'd video content 103 | */ 104 | async signDrmLicense( 105 | playbackId: string, 106 | config: MuxJWTSignOptions = {}, 107 | ): Promise { 108 | const claim = TypeClaim[config.type ?? 'drm_license']; 109 | if (!claim) { 110 | throw new Error(`Invalid signature type: ${config.type}; Expected one of ${Object.keys(TypeClaim)}`); 111 | } 112 | 113 | const tokenOptions: SignOptions = { 114 | keyid: jwt.getSigningKey(this._client, config), 115 | subject: playbackId, 116 | audience: claim, 117 | expiresIn: config.expiration ?? '7d', 118 | noTimestamp: true, 119 | algorithm: 'RS256', 120 | }; 121 | 122 | return jwt.sign(config.params ?? {}, await jwt.getPrivateKey(this._client, config), tokenOptions); 123 | } 124 | 125 | /** 126 | * Creates a new token to be used with a space 127 | * @deprecated Mux Real-Time Video (spaces) has been shut down. This function will be removed in the next major version. 128 | */ 129 | async signSpaceId(spaceId: string, config: MuxJWTSignOptions = {}): Promise { 130 | const tokenOptions: SignOptions = { 131 | keyid: jwt.getSigningKey(this._client, config), 132 | subject: spaceId, 133 | audience: 'rt', 134 | expiresIn: config.expiration ?? '7d', 135 | noTimestamp: true, 136 | algorithm: 'RS256', 137 | }; 138 | 139 | return jwt.sign(config.params ?? {}, await jwt.getPrivateKey(this._client, config), tokenOptions); 140 | } 141 | 142 | /** 143 | * Creates a new token to be used with a signed statistics request 144 | */ 145 | async signViewerCounts( 146 | id: string, 147 | config: MuxJWTSignOptions = {}, 148 | ): Promise { 149 | const claim = DataTypeClaim[config.type ?? 'video']; 150 | if (!claim) { 151 | throw new Error( 152 | `Invalid signature type: ${config.type}; Expected one of ${Object.keys(DataTypeClaim)}`, 153 | ); 154 | } 155 | 156 | const tokenOptions: SignOptions = { 157 | keyid: jwt.getSigningKey(this._client, config), 158 | subject: id, 159 | audience: claim, 160 | expiresIn: config.expiration ?? '7d', 161 | noTimestamp: true, 162 | algorithm: 'RS256', 163 | }; 164 | 165 | return jwt.sign(config.params ?? {}, await jwt.getPrivateKey(this._client, config), tokenOptions); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/resources/shared.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export interface PlaybackID { 4 | /** 5 | * Unique identifier for the PlaybackID 6 | */ 7 | id: string; 8 | 9 | /** 10 | * - `public` playback IDs are accessible by constructing an HLS URL like 11 | * `https://stream.mux.com/${PLAYBACK_ID}` 12 | * 13 | * - `signed` playback IDs should be used with tokens 14 | * `https://stream.mux.com/${PLAYBACK_ID}?token={TOKEN}`. See 15 | * [Secure video playback](https://docs.mux.com/guides/secure-video-playback) for 16 | * details about creating tokens. 17 | * 18 | * - `drm` playback IDs are protected with DRM technologies. 19 | * [See DRM documentation for more details](https://docs.mux.com/guides/protect-videos-with-drm). 20 | */ 21 | policy: PlaybackPolicy; 22 | 23 | /** 24 | * The DRM configuration used by this playback ID. Must only be set when `policy` 25 | * is set to `drm`. 26 | */ 27 | drm_configuration_id?: string; 28 | } 29 | 30 | /** 31 | * - `public` playback IDs are accessible by constructing an HLS URL like 32 | * `https://stream.mux.com/${PLAYBACK_ID}` 33 | * 34 | * - `signed` playback IDs should be used with tokens 35 | * `https://stream.mux.com/${PLAYBACK_ID}?token={TOKEN}`. See 36 | * [Secure video playback](https://docs.mux.com/guides/secure-video-playback) for 37 | * details about creating tokens. 38 | * 39 | * - `drm` playback IDs are protected with DRM technologies. 40 | * [See DRM documentation for more details](https://docs.mux.com/guides/protect-videos-with-drm). 41 | */ 42 | export type PlaybackPolicy = 'public' | 'signed' | 'drm'; 43 | -------------------------------------------------------------------------------- /src/resources/system.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './system/index'; 4 | -------------------------------------------------------------------------------- /src/resources/system/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { 4 | SigningKeysBasePage, 5 | SigningKeys, 6 | type SigningKey, 7 | type SigningKeyResponse, 8 | type SigningKeyListParams, 9 | } from './signing-keys'; 10 | export { System } from './system'; 11 | -------------------------------------------------------------------------------- /src/resources/system/signing-keys.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import { isRequestOptions } from '../../core'; 5 | import * as Core from '../../core'; 6 | import { BasePage, type BasePageParams } from '../../pagination'; 7 | 8 | export class SigningKeys extends APIResource { 9 | /** 10 | * Creates a new signing key pair. When creating a new signing key, the API will 11 | * generate a 2048-bit RSA key-pair and return the private key and a generated 12 | * key-id; the public key will be stored at Mux to validate signed tokens. 13 | */ 14 | create(options?: Core.RequestOptions): Core.APIPromise { 15 | return ( 16 | this._client.post('/system/v1/signing-keys', options) as Core.APIPromise<{ data: SigningKey }> 17 | )._thenUnwrap((obj) => obj.data); 18 | } 19 | 20 | /** 21 | * Retrieves the details of a signing key that has previously been created. Supply 22 | * the unique signing key ID that was returned from your previous request, and Mux 23 | * will return the corresponding signing key information. **The private key is not 24 | * returned in this response.** 25 | */ 26 | retrieve(signingKeyId: string, options?: Core.RequestOptions): Core.APIPromise { 27 | return ( 28 | this._client.get(`/system/v1/signing-keys/${signingKeyId}`, options) as Core.APIPromise<{ 29 | data: SigningKey; 30 | }> 31 | )._thenUnwrap((obj) => obj.data); 32 | } 33 | 34 | /** 35 | * Returns a list of signing keys. 36 | */ 37 | list( 38 | query?: SigningKeyListParams, 39 | options?: Core.RequestOptions, 40 | ): Core.PagePromise; 41 | list(options?: Core.RequestOptions): Core.PagePromise; 42 | list( 43 | query: SigningKeyListParams | Core.RequestOptions = {}, 44 | options?: Core.RequestOptions, 45 | ): Core.PagePromise { 46 | if (isRequestOptions(query)) { 47 | return this.list({}, query); 48 | } 49 | return this._client.getAPIList('/system/v1/signing-keys', SigningKeysBasePage, { query, ...options }); 50 | } 51 | 52 | /** 53 | * Deletes an existing signing key. Use with caution, as this will invalidate any 54 | * existing signatures and no JWTs can be signed using the key again. 55 | */ 56 | delete(signingKeyId: string, options?: Core.RequestOptions): Core.APIPromise { 57 | return this._client.delete(`/system/v1/signing-keys/${signingKeyId}`, { 58 | ...options, 59 | headers: { Accept: '*/*', ...options?.headers }, 60 | }); 61 | } 62 | } 63 | 64 | export class SigningKeysBasePage extends BasePage {} 65 | 66 | export interface SigningKey { 67 | /** 68 | * Unique identifier for the Signing Key. 69 | */ 70 | id: string; 71 | 72 | /** 73 | * Time at which the object was created. Measured in seconds since the Unix epoch. 74 | */ 75 | created_at: string; 76 | 77 | /** 78 | * A Base64 encoded private key that can be used with the RS256 algorithm when 79 | * creating a [JWT](https://jwt.io/). **Note that this value is only returned once 80 | * when creating a URL signing key.** 81 | */ 82 | private_key?: string; 83 | } 84 | 85 | export interface SigningKeyResponse { 86 | data: SigningKey; 87 | } 88 | 89 | export interface SigningKeyListParams extends BasePageParams {} 90 | 91 | SigningKeys.SigningKeysBasePage = SigningKeysBasePage; 92 | 93 | export declare namespace SigningKeys { 94 | export { 95 | type SigningKey as SigningKey, 96 | type SigningKeyResponse as SigningKeyResponse, 97 | SigningKeysBasePage as SigningKeysBasePage, 98 | type SigningKeyListParams as SigningKeyListParams, 99 | }; 100 | } 101 | -------------------------------------------------------------------------------- /src/resources/system/system.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import * as SigningKeysAPI from './signing-keys'; 5 | import { 6 | SigningKey, 7 | SigningKeyListParams, 8 | SigningKeyResponse, 9 | SigningKeys, 10 | SigningKeysBasePage, 11 | } from './signing-keys'; 12 | 13 | export class System extends APIResource { 14 | signingKeys: SigningKeysAPI.SigningKeys = new SigningKeysAPI.SigningKeys(this._client); 15 | } 16 | 17 | System.SigningKeys = SigningKeys; 18 | System.SigningKeysBasePage = SigningKeysBasePage; 19 | 20 | export declare namespace System { 21 | export { 22 | SigningKeys as SigningKeys, 23 | type SigningKey as SigningKey, 24 | type SigningKeyResponse as SigningKeyResponse, 25 | SigningKeysBasePage as SigningKeysBasePage, 26 | type SigningKeyListParams as SigningKeyListParams, 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /src/resources/video.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './video/index'; 4 | -------------------------------------------------------------------------------- /src/resources/video/delivery-usage.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import { isRequestOptions } from '../../core'; 5 | import * as Core from '../../core'; 6 | import { PageWithTotal, type PageWithTotalParams } from '../../pagination'; 7 | 8 | export class DeliveryUsage extends APIResource { 9 | /** 10 | * Returns a list of delivery usage records and their associated Asset IDs or Live 11 | * Stream IDs. 12 | * 13 | * @example 14 | * ```ts 15 | * // Automatically fetches more pages as needed. 16 | * for await (const deliveryReport of client.video.deliveryUsage.list()) { 17 | * // ... 18 | * } 19 | * ``` 20 | */ 21 | list( 22 | query?: DeliveryUsageListParams, 23 | options?: Core.RequestOptions, 24 | ): Core.PagePromise; 25 | list(options?: Core.RequestOptions): Core.PagePromise; 26 | list( 27 | query: DeliveryUsageListParams | Core.RequestOptions = {}, 28 | options?: Core.RequestOptions, 29 | ): Core.PagePromise { 30 | if (isRequestOptions(query)) { 31 | return this.list({}, query); 32 | } 33 | return this._client.getAPIList('/video/v1/delivery-usage', DeliveryReportsPageWithTotal, { 34 | query, 35 | ...options, 36 | }); 37 | } 38 | } 39 | 40 | export class DeliveryReportsPageWithTotal extends PageWithTotal {} 41 | 42 | export interface DeliveryReport { 43 | /** 44 | * The duration of the asset in seconds. 45 | */ 46 | asset_duration: number; 47 | 48 | /** 49 | * @deprecated This field is deprecated. Please use `asset_video_quality` instead. 50 | * The encoding tier that the asset was ingested at. 51 | * [See the video quality guide for more details.](https://docs.mux.com/guides/use-video-quality-levels) 52 | */ 53 | asset_encoding_tier: 'smart' | 'baseline' | 'premium'; 54 | 55 | /** 56 | * Unique identifier for the asset. 57 | */ 58 | asset_id: string; 59 | 60 | /** 61 | * The resolution tier that the asset was ingested at, affecting billing for ingest 62 | * & storage 63 | */ 64 | asset_resolution_tier: 'audio-only' | '720p' | '1080p' | '1440p' | '2160p'; 65 | 66 | /** 67 | * The state of the asset. 68 | */ 69 | asset_state: 'ready' | 'errored' | 'deleted'; 70 | 71 | /** 72 | * Time at which the asset was created. Measured in seconds since the Unix epoch. 73 | */ 74 | created_at: string; 75 | 76 | /** 77 | * Total number of delivered seconds during this time window. 78 | */ 79 | delivered_seconds: number; 80 | 81 | /** 82 | * Seconds delivered broken into resolution tiers. Each tier will only be displayed 83 | * if there was content delivered in the tier. 84 | */ 85 | delivered_seconds_by_resolution: DeliveryReport.DeliveredSecondsByResolution; 86 | 87 | /** 88 | * The video quality that the asset was ingested at. This field replaces 89 | * `asset_encoding_tier`. 90 | * [See the video quality guide for more details.](https://docs.mux.com/guides/use-video-quality-levels) 91 | */ 92 | asset_video_quality?: 'basic' | 'plus' | 'premium'; 93 | 94 | /** 95 | * If exists, time at which the asset was deleted. Measured in seconds since the 96 | * Unix epoch. 97 | */ 98 | deleted_at?: string; 99 | 100 | /** 101 | * Unique identifier for the live stream that created the asset. 102 | */ 103 | live_stream_id?: string; 104 | 105 | /** 106 | * The `passthrough` value for the asset. 107 | */ 108 | passthrough?: string; 109 | } 110 | 111 | export namespace DeliveryReport { 112 | /** 113 | * Seconds delivered broken into resolution tiers. Each tier will only be displayed 114 | * if there was content delivered in the tier. 115 | */ 116 | export interface DeliveredSecondsByResolution { 117 | /** 118 | * Total number of delivered seconds during this time window that had a resolution 119 | * larger than the 720p tier but less than or equal to the 1440p tier (over 921,600 120 | * and <= 2,073,600 pixels total). 121 | */ 122 | tier_1080p?: number; 123 | 124 | /** 125 | * Total number of delivered seconds during this time window that had a resolution 126 | * larger than the 1080p tier but less than or equal to the 2160p tier (over 127 | * 2,073,600 and <= 4,194,304 pixels total). 128 | */ 129 | tier_1440p?: number; 130 | 131 | /** 132 | * Total number of delivered seconds during this time window that had a resolution 133 | * larger than the 1440p tier (over 4,194,304 pixels total). 134 | */ 135 | tier_2160p?: number; 136 | 137 | /** 138 | * Total number of delivered seconds during this time window that had a resolution 139 | * within the 720p tier (up to 921,600 pixels total, based on typical 1280x720). 140 | */ 141 | tier_720p?: number; 142 | 143 | /** 144 | * Total number of delivered seconds during this time window that had a resolution 145 | * of audio only. 146 | */ 147 | tier_audio_only?: number; 148 | } 149 | } 150 | 151 | export interface DeliveryUsageListParams extends PageWithTotalParams { 152 | /** 153 | * Filter response to return delivery usage for this asset only. You cannot specify 154 | * both the `asset_id` and `live_stream_id` parameters together. 155 | */ 156 | asset_id?: string; 157 | 158 | /** 159 | * Filter response to return delivery usage for assets for this live stream. You 160 | * cannot specify both the `asset_id` and `live_stream_id` parameters together. 161 | */ 162 | live_stream_id?: string; 163 | 164 | /** 165 | * Time window to get delivery usage information. timeframe[0] indicates the start 166 | * time, timeframe[1] indicates the end time in seconds since the Unix epoch. 167 | * Default time window is 1 hour representing usage from 13th to 12th hour from 168 | * when the request is made. 169 | */ 170 | timeframe?: Array; 171 | } 172 | 173 | DeliveryUsage.DeliveryReportsPageWithTotal = DeliveryReportsPageWithTotal; 174 | 175 | export declare namespace DeliveryUsage { 176 | export { 177 | type DeliveryReport as DeliveryReport, 178 | DeliveryReportsPageWithTotal as DeliveryReportsPageWithTotal, 179 | type DeliveryUsageListParams as DeliveryUsageListParams, 180 | }; 181 | } 182 | -------------------------------------------------------------------------------- /src/resources/video/drm-configurations.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import { isRequestOptions } from '../../core'; 5 | import * as Core from '../../core'; 6 | import { BasePage, type BasePageParams } from '../../pagination'; 7 | 8 | export class DRMConfigurations extends APIResource { 9 | /** 10 | * Retrieves a single DRM Configuration. 11 | * 12 | * @example 13 | * ```ts 14 | * const drmConfiguration = 15 | * await client.video.drmConfigurations.retrieve( 16 | * 'DRM_CONFIGURATION_ID', 17 | * ); 18 | * ``` 19 | */ 20 | retrieve(drmConfigurationId: string, options?: Core.RequestOptions): Core.APIPromise { 21 | return ( 22 | this._client.get(`/video/v1/drm-configurations/${drmConfigurationId}`, options) as Core.APIPromise<{ 23 | data: DRMConfiguration; 24 | }> 25 | )._thenUnwrap((obj) => obj.data); 26 | } 27 | 28 | /** 29 | * Returns a list of DRM Configurations 30 | * 31 | * @example 32 | * ```ts 33 | * // Automatically fetches more pages as needed. 34 | * for await (const drmConfiguration of client.video.drmConfigurations.list()) { 35 | * // ... 36 | * } 37 | * ``` 38 | */ 39 | list( 40 | query?: DRMConfigurationListParams, 41 | options?: Core.RequestOptions, 42 | ): Core.PagePromise; 43 | list(options?: Core.RequestOptions): Core.PagePromise; 44 | list( 45 | query: DRMConfigurationListParams | Core.RequestOptions = {}, 46 | options?: Core.RequestOptions, 47 | ): Core.PagePromise { 48 | if (isRequestOptions(query)) { 49 | return this.list({}, query); 50 | } 51 | return this._client.getAPIList('/video/v1/drm-configurations', DRMConfigurationsBasePage, { 52 | query, 53 | ...options, 54 | }); 55 | } 56 | } 57 | 58 | export class DRMConfigurationsBasePage extends BasePage {} 59 | 60 | export interface DRMConfiguration { 61 | /** 62 | * Unique identifier for the DRM Configuration. Max 255 characters. 63 | */ 64 | id: string; 65 | } 66 | 67 | export interface DRMConfigurationListParams extends BasePageParams {} 68 | 69 | DRMConfigurations.DRMConfigurationsBasePage = DRMConfigurationsBasePage; 70 | 71 | export declare namespace DRMConfigurations { 72 | export { 73 | type DRMConfiguration as DRMConfiguration, 74 | DRMConfigurationsBasePage as DRMConfigurationsBasePage, 75 | type DRMConfigurationListParams as DRMConfigurationListParams, 76 | }; 77 | } 78 | -------------------------------------------------------------------------------- /src/resources/video/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { 4 | AssetsBasePage, 5 | Assets, 6 | type Asset, 7 | type AssetOptions, 8 | type AssetResponse, 9 | type InputInfo, 10 | type Track, 11 | type AssetCreateStaticRenditionResponse, 12 | type AssetGenerateSubtitlesResponse, 13 | type AssetRetrieveInputInfoResponse, 14 | type AssetCreateParams, 15 | type AssetUpdateParams, 16 | type AssetListParams, 17 | type AssetCreatePlaybackIDParams, 18 | type AssetCreateStaticRenditionParams, 19 | type AssetCreateTrackParams, 20 | type AssetGenerateSubtitlesParams, 21 | type AssetUpdateMasterAccessParams, 22 | type AssetUpdateMP4SupportParams, 23 | } from './assets'; 24 | export { 25 | DRMConfigurationsBasePage, 26 | DRMConfigurations, 27 | type DRMConfiguration, 28 | type DRMConfigurationListParams, 29 | } from './drm-configurations'; 30 | export { 31 | DeliveryReportsPageWithTotal, 32 | DeliveryUsage, 33 | type DeliveryReport, 34 | type DeliveryUsageListParams, 35 | } from './delivery-usage'; 36 | export { 37 | LiveStreamsBasePage, 38 | LiveStreams, 39 | type LiveStream, 40 | type SimulcastTarget, 41 | type LiveStreamCreateParams, 42 | type LiveStreamUpdateParams, 43 | type LiveStreamListParams, 44 | type LiveStreamCreatePlaybackIDParams, 45 | type LiveStreamCreateSimulcastTargetParams, 46 | type LiveStreamUpdateEmbeddedSubtitlesParams, 47 | type LiveStreamUpdateGeneratedSubtitlesParams, 48 | type LiveStreamUpdateNewAssetSettingsStaticRenditionsParams, 49 | } from './live-streams'; 50 | export { PlaybackIDs, type PlaybackIDRetrieveResponse } from './playback-ids'; 51 | export { 52 | PlaybackRestrictionsBasePage, 53 | PlaybackRestrictions, 54 | type PlaybackRestriction, 55 | type PlaybackRestrictionResponse, 56 | type PlaybackRestrictionCreateParams, 57 | type PlaybackRestrictionListParams, 58 | type PlaybackRestrictionUpdateReferrerParams, 59 | type PlaybackRestrictionUpdateUserAgentParams, 60 | } from './playback-restrictions'; 61 | export { 62 | TranscriptionVocabulariesBasePage, 63 | TranscriptionVocabularies, 64 | type TranscriptionVocabulary, 65 | type TranscriptionVocabularyResponse, 66 | type TranscriptionVocabularyCreateParams, 67 | type TranscriptionVocabularyUpdateParams, 68 | type TranscriptionVocabularyListParams, 69 | } from './transcription-vocabularies'; 70 | export { 71 | UploadsBasePage, 72 | Uploads, 73 | type Upload, 74 | type UploadResponse, 75 | type UploadCreateParams, 76 | type UploadListParams, 77 | } from './uploads'; 78 | export { Video } from './video'; 79 | export { 80 | WebInputListResponsesBasePage, 81 | WebInputs, 82 | type WebInputCreateResponse, 83 | type WebInputRetrieveResponse, 84 | type WebInputListResponse, 85 | type WebInputLaunchResponse, 86 | type WebInputReloadResponse, 87 | type WebInputShutdownResponse, 88 | type WebInputUpdateURLResponse, 89 | type WebInputCreateParams, 90 | type WebInputListParams, 91 | type WebInputUpdateURLParams, 92 | } from './web-inputs'; 93 | -------------------------------------------------------------------------------- /src/resources/video/playback-ids.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import * as Core from '../../core'; 5 | import * as Shared from '../shared'; 6 | 7 | export class PlaybackIDs extends APIResource { 8 | /** 9 | * Retrieves the Identifier of the Asset or Live Stream associated with the 10 | * Playback ID. 11 | * 12 | * @example 13 | * ```ts 14 | * const playbackId = await client.video.playbackIds.retrieve( 15 | * 'PLAYBACK_ID', 16 | * ); 17 | * ``` 18 | */ 19 | retrieve(playbackId: string, options?: Core.RequestOptions): Core.APIPromise { 20 | return ( 21 | this._client.get(`/video/v1/playback-ids/${playbackId}`, options) as Core.APIPromise<{ 22 | data: PlaybackIDRetrieveResponse; 23 | }> 24 | )._thenUnwrap((obj) => obj.data); 25 | } 26 | } 27 | 28 | export interface PlaybackIDRetrieveResponse { 29 | /** 30 | * The Playback ID used to retrieve the corresponding asset or the live stream ID 31 | */ 32 | id: string; 33 | 34 | /** 35 | * Describes the Asset or LiveStream object associated with the playback ID. 36 | */ 37 | object: PlaybackIDRetrieveResponse.Object; 38 | 39 | /** 40 | * - `public` playback IDs are accessible by constructing an HLS URL like 41 | * `https://stream.mux.com/${PLAYBACK_ID}` 42 | * 43 | * - `signed` playback IDs should be used with tokens 44 | * `https://stream.mux.com/${PLAYBACK_ID}?token={TOKEN}`. See 45 | * [Secure video playback](https://docs.mux.com/guides/secure-video-playback) for 46 | * details about creating tokens. 47 | * 48 | * - `drm` playback IDs are protected with DRM technologies. 49 | * [See DRM documentation for more details](https://docs.mux.com/guides/protect-videos-with-drm). 50 | */ 51 | policy: Shared.PlaybackPolicy; 52 | } 53 | 54 | export namespace PlaybackIDRetrieveResponse { 55 | /** 56 | * Describes the Asset or LiveStream object associated with the playback ID. 57 | */ 58 | export interface Object { 59 | /** 60 | * The identifier of the object. 61 | */ 62 | id: string; 63 | 64 | /** 65 | * Identifies the object type associated with the playback ID. 66 | */ 67 | type: 'asset' | 'live_stream'; 68 | } 69 | } 70 | 71 | export declare namespace PlaybackIDs { 72 | export { type PlaybackIDRetrieveResponse as PlaybackIDRetrieveResponse }; 73 | } 74 | -------------------------------------------------------------------------------- /src/resources/video/uploads.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import { isRequestOptions } from '../../core'; 5 | import * as Core from '../../core'; 6 | import * as AssetsAPI from './assets'; 7 | import { BasePage, type BasePageParams } from '../../pagination'; 8 | 9 | export class Uploads extends APIResource { 10 | /** 11 | * Creates a new direct upload, through which video content can be uploaded for 12 | * ingest to Mux. 13 | * 14 | * @example 15 | * ```ts 16 | * const upload = await client.video.uploads.create({ 17 | * cors_origin: 'https://example.com/', 18 | * new_asset_settings: { playback_policies: ['public'] }, 19 | * }); 20 | * ``` 21 | */ 22 | create(body: UploadCreateParams, options?: Core.RequestOptions): Core.APIPromise { 23 | return ( 24 | this._client.post('/video/v1/uploads', { body, ...options }) as Core.APIPromise<{ data: Upload }> 25 | )._thenUnwrap((obj) => obj.data); 26 | } 27 | 28 | /** 29 | * Fetches information about a single direct upload in the current environment. 30 | * 31 | * @example 32 | * ```ts 33 | * const upload = await client.video.uploads.retrieve( 34 | * 'abcd1234', 35 | * ); 36 | * ``` 37 | */ 38 | retrieve(uploadId: string, options?: Core.RequestOptions): Core.APIPromise { 39 | return ( 40 | this._client.get(`/video/v1/uploads/${uploadId}`, options) as Core.APIPromise<{ data: Upload }> 41 | )._thenUnwrap((obj) => obj.data); 42 | } 43 | 44 | /** 45 | * Lists direct uploads in the current environment. 46 | * 47 | * @example 48 | * ```ts 49 | * // Automatically fetches more pages as needed. 50 | * for await (const upload of client.video.uploads.list()) { 51 | * // ... 52 | * } 53 | * ``` 54 | */ 55 | list(query?: UploadListParams, options?: Core.RequestOptions): Core.PagePromise; 56 | list(options?: Core.RequestOptions): Core.PagePromise; 57 | list( 58 | query: UploadListParams | Core.RequestOptions = {}, 59 | options?: Core.RequestOptions, 60 | ): Core.PagePromise { 61 | if (isRequestOptions(query)) { 62 | return this.list({}, query); 63 | } 64 | return this._client.getAPIList('/video/v1/uploads', UploadsBasePage, { query, ...options }); 65 | } 66 | 67 | /** 68 | * Cancels a direct upload and marks it as cancelled. If a pending upload finishes 69 | * after this request, no asset will be created. This request will only succeed if 70 | * the upload is still in the `waiting` state. 71 | * 72 | * @example 73 | * ```ts 74 | * const upload = await client.video.uploads.cancel( 75 | * 'abcd1234', 76 | * ); 77 | * ``` 78 | */ 79 | cancel(uploadId: string, options?: Core.RequestOptions): Core.APIPromise { 80 | return ( 81 | this._client.put(`/video/v1/uploads/${uploadId}/cancel`, options) as Core.APIPromise<{ data: Upload }> 82 | )._thenUnwrap((obj) => obj.data); 83 | } 84 | } 85 | 86 | export class UploadsBasePage extends BasePage {} 87 | 88 | export interface Upload { 89 | /** 90 | * Unique identifier for the Direct Upload. 91 | */ 92 | id: string; 93 | 94 | /** 95 | * If the upload URL will be used in a browser, you must specify the origin in 96 | * order for the signed URL to have the correct CORS headers. 97 | */ 98 | cors_origin: string; 99 | 100 | status: 'waiting' | 'asset_created' | 'errored' | 'cancelled' | 'timed_out'; 101 | 102 | /** 103 | * Max time in seconds for the signed upload URL to be valid. If a successful 104 | * upload has not occurred before the timeout limit, the direct upload is marked 105 | * `timed_out` 106 | */ 107 | timeout: number; 108 | 109 | /** 110 | * The URL to upload the associated source media to. 111 | */ 112 | url: string; 113 | 114 | /** 115 | * Only set once the upload is in the `asset_created` state. 116 | */ 117 | asset_id?: string; 118 | 119 | /** 120 | * Only set if an error occurred during asset creation. 121 | */ 122 | error?: Upload.Error; 123 | 124 | new_asset_settings?: AssetsAPI.AssetOptions; 125 | 126 | /** 127 | * Indicates if this is a test Direct Upload, in which case the Asset that gets 128 | * created will be a `test` Asset. 129 | */ 130 | test?: boolean; 131 | } 132 | 133 | export namespace Upload { 134 | /** 135 | * Only set if an error occurred during asset creation. 136 | */ 137 | export interface Error { 138 | /** 139 | * Human readable error message 140 | */ 141 | message?: string; 142 | 143 | /** 144 | * Label for the specific error 145 | */ 146 | type?: string; 147 | } 148 | } 149 | 150 | export interface UploadResponse { 151 | data: Upload; 152 | } 153 | 154 | export interface UploadCreateParams { 155 | /** 156 | * If the upload URL will be used in a browser, you must specify the origin in 157 | * order for the signed URL to have the correct CORS headers. 158 | */ 159 | cors_origin: string; 160 | 161 | new_asset_settings?: AssetsAPI.AssetOptions; 162 | 163 | /** 164 | * Indicates if this is a test Direct Upload, in which case the Asset that gets 165 | * created will be a `test` Asset. 166 | */ 167 | test?: boolean; 168 | 169 | /** 170 | * Max time in seconds for the signed upload URL to be valid. If a successful 171 | * upload has not occurred before the timeout limit, the direct upload is marked 172 | * `timed_out` 173 | */ 174 | timeout?: number; 175 | } 176 | 177 | export interface UploadListParams extends BasePageParams {} 178 | 179 | Uploads.UploadsBasePage = UploadsBasePage; 180 | 181 | export declare namespace Uploads { 182 | export { 183 | type Upload as Upload, 184 | type UploadResponse as UploadResponse, 185 | UploadsBasePage as UploadsBasePage, 186 | type UploadCreateParams as UploadCreateParams, 187 | type UploadListParams as UploadListParams, 188 | }; 189 | } 190 | -------------------------------------------------------------------------------- /src/shims/node.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import * as types from '../_shims/node-types'; 3 | import { setShims } from '../_shims/registry'; 4 | import { getRuntime } from '../_shims/node-runtime'; 5 | setShims(getRuntime()); 6 | 7 | declare module '../_shims/manual-types' { 8 | export namespace manual { 9 | // @ts-ignore 10 | export type Agent = types.Agent; 11 | // @ts-ignore 12 | export import fetch = types.fetch; 13 | // @ts-ignore 14 | export type Request = types.Request; 15 | // @ts-ignore 16 | export type RequestInfo = types.RequestInfo; 17 | // @ts-ignore 18 | export type RequestInit = types.RequestInit; 19 | // @ts-ignore 20 | export type Response = types.Response; 21 | // @ts-ignore 22 | export type ResponseInit = types.ResponseInit; 23 | // @ts-ignore 24 | export type ResponseType = types.ResponseType; 25 | // @ts-ignore 26 | export type BodyInit = types.BodyInit; 27 | // @ts-ignore 28 | export type Headers = types.Headers; 29 | // @ts-ignore 30 | export type HeadersInit = types.HeadersInit; 31 | // @ts-ignore 32 | export type BlobPropertyBag = types.BlobPropertyBag; 33 | // @ts-ignore 34 | export type FilePropertyBag = types.FilePropertyBag; 35 | // @ts-ignore 36 | export type FileFromPathOptions = types.FileFromPathOptions; 37 | // @ts-ignore 38 | export import FormData = types.FormData; 39 | // @ts-ignore 40 | export import File = types.File; 41 | // @ts-ignore 42 | export import Blob = types.Blob; 43 | // @ts-ignore 44 | export type Readable = types.Readable; 45 | // @ts-ignore 46 | export type FsReadStream = types.FsReadStream; 47 | // @ts-ignore 48 | export import ReadableStream = types.ReadableStream; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/shims/web.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import * as types from '../_shims/web-types'; 3 | import { setShims } from '../_shims/registry'; 4 | import { getRuntime } from '../_shims/web-runtime'; 5 | setShims(getRuntime({ manuallyImported: true })); 6 | 7 | declare module '../_shims/manual-types' { 8 | export namespace manual { 9 | // @ts-ignore 10 | export type Agent = types.Agent; 11 | // @ts-ignore 12 | export import fetch = types.fetch; 13 | // @ts-ignore 14 | export type Request = types.Request; 15 | // @ts-ignore 16 | export type RequestInfo = types.RequestInfo; 17 | // @ts-ignore 18 | export type RequestInit = types.RequestInit; 19 | // @ts-ignore 20 | export type Response = types.Response; 21 | // @ts-ignore 22 | export type ResponseInit = types.ResponseInit; 23 | // @ts-ignore 24 | export type ResponseType = types.ResponseType; 25 | // @ts-ignore 26 | export type BodyInit = types.BodyInit; 27 | // @ts-ignore 28 | export type Headers = types.Headers; 29 | // @ts-ignore 30 | export type HeadersInit = types.HeadersInit; 31 | // @ts-ignore 32 | export type BlobPropertyBag = types.BlobPropertyBag; 33 | // @ts-ignore 34 | export type FilePropertyBag = types.FilePropertyBag; 35 | // @ts-ignore 36 | export type FileFromPathOptions = types.FileFromPathOptions; 37 | // @ts-ignore 38 | export import FormData = types.FormData; 39 | // @ts-ignore 40 | export import File = types.File; 41 | // @ts-ignore 42 | export import Blob = types.Blob; 43 | // @ts-ignore 44 | export type Readable = types.Readable; 45 | // @ts-ignore 46 | export type FsReadStream = types.FsReadStream; 47 | // @ts-ignore 48 | export import ReadableStream = types.ReadableStream; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/util/jwt-types.ts: -------------------------------------------------------------------------------- 1 | import { type PrivateKey } from '@mux/mux-node/_shims/auto/jwt'; 2 | 3 | export interface SignOptions { 4 | /** 5 | * Signature algorithm. Could be one of these values : 6 | * - RS256: RSASSA using SHA-256 hash algorithm 7 | */ 8 | algorithm?: Algorithm | undefined; 9 | keyid?: string | undefined; 10 | /** expressed in seconds or a string describing a time span [zeit/ms](https://github.com/zeit/ms.js). Eg: 60, "2 days", "10h", "7d" */ 11 | expiresIn?: string | number | undefined; 12 | /** expressed in seconds or a string describing a time span [zeit/ms](https://github.com/zeit/ms.js). Eg: 60, "2 days", "10h", "7d" */ 13 | notBefore?: string | number | undefined; 14 | audience?: string | string[] | undefined; 15 | subject?: string | undefined; 16 | issuer?: string | undefined; 17 | jwtid?: string | undefined; 18 | noTimestamp?: boolean | undefined; 19 | } 20 | 21 | export type Algorithm = 'RS256'; 22 | 23 | // standard names https://www.rfc-editor.org/rfc/rfc7515.html#section-4.1 24 | export interface JwtHeader { 25 | alg: string | Algorithm; 26 | typ?: string | undefined; 27 | cty?: string | undefined; 28 | crit?: Array> | undefined; 29 | kid?: string | undefined; 30 | jku?: string | undefined; 31 | x5u?: string | string[] | undefined; 32 | 'x5t#S256'?: string | undefined; 33 | x5t?: string | undefined; 34 | x5c?: string | string[] | undefined; 35 | } 36 | 37 | export enum TypeClaim { 38 | video = 'v', 39 | thumbnail = 't', 40 | gif = 'g', 41 | storyboard = 's', 42 | stats = 'playback_id', 43 | drm_license = 'd', 44 | } 45 | export enum TypeToken { 46 | video = 'playback-token', 47 | thumbnail = 'thumbnail-token', 48 | storyboard = 'storyboard-token', 49 | drm_license = 'drm-token', 50 | gif = 'gif-token', // Not supported by Mux Player 51 | stats = 'stats-token', // Not supported by Mux Player 52 | } 53 | export type TypeTokenValues = (typeof TypeToken)[keyof typeof TypeToken]; 54 | export type Tokens = Partial>; 55 | // ['thumbnail', { time: 2 }] 56 | export type TypeWithParams = [Type, MuxJWTSignOptions['params']]; 57 | 58 | interface MuxJWTSignOptionsBase { 59 | keyId?: string; 60 | keySecret?: string | PrivateKey; 61 | keyFilePath?: string; 62 | type?: Type | Array>; 63 | expiration?: string; 64 | params?: Record; 65 | } 66 | export interface MuxJWTSignOptions extends MuxJWTSignOptionsBase { 67 | type?: Type; 68 | } 69 | export interface MuxJWTSignOptionsMultiple extends MuxJWTSignOptionsBase { 70 | type: Array>; 71 | } 72 | export const isMuxJWTSignOptionsMultiple = ( 73 | config: MuxJWTSignOptions | MuxJWTSignOptionsMultiple, 74 | ): config is MuxJWTSignOptionsMultiple => Array.isArray(config.type); 75 | 76 | export enum DataTypeClaim { 77 | video = 'video_id', 78 | asset = 'asset_id', 79 | playback = 'playback_id', 80 | live_stream = 'live_stream_id', 81 | } 82 | -------------------------------------------------------------------------------- /src/util/jwt-util.ts: -------------------------------------------------------------------------------- 1 | export function isKeyLike(key: any): key is { type: string } { 2 | return typeof key === 'object' && key != null && typeof (key as any).type === 'string'; 3 | } 4 | 5 | export const keyFormatErrorMessage = 6 | 'Specified signing key must be either a valid PKCS1 or PKCS8 PEM string, a base64 encoded PEM, or an imported key'; 7 | 8 | export function base64ToUint8Array(base64: string): Uint8Array { 9 | const binaryString = atob(base64); 10 | const bytes = new Uint8Array(binaryString.length); 11 | for (var i = 0; i < binaryString.length; i++) { 12 | bytes[i] = binaryString.charCodeAt(i); 13 | } 14 | return bytes; 15 | } 16 | 17 | export function uint8ArrayToBase64(array: Uint8Array): String { 18 | return btoa([...array].map((byte) => String.fromCharCode(byte)).join('')); 19 | } 20 | 21 | export function unwrapPem(key: string): Uint8Array { 22 | return base64ToUint8Array( 23 | key 24 | .trim() 25 | .replace(/\n/gm, '') 26 | .replace(/^-----[A-Z ]+-----|-----[A-Z ]+-----$/g, ''), 27 | ); 28 | } 29 | 30 | export function toPkcs8Pem(key: Uint8Array) { 31 | const parts = ['-----BEGIN PRIVATE KEY-----']; 32 | const base64 = uint8ArrayToBase64(key); 33 | for (let i = 0; i < base64.length; i += 64) { 34 | parts.push(base64.substring(i, i + 64)); 35 | } 36 | parts.push('-----END PRIVATE KEY-----'); 37 | return parts.join('\n'); 38 | } 39 | 40 | const certAndRsa = Uint8Array.of( 41 | 0x02, 42 | 0x01, 43 | 0x00, 44 | 0x30, 45 | 0x0d, 46 | 0x06, 47 | 0x09, 48 | 0x2a, 49 | 0x86, 50 | 0x48, 51 | 0x86, 52 | 0xf7, 53 | 0x0d, 54 | 0x01, 55 | 0x01, 56 | 0x01, 57 | 0x05, 58 | 0x00, 59 | ); 60 | 61 | // All of this just to wrap a PKCS1 signature into a form that web crypto 62 | // can import! 63 | const DER = { 64 | lengthBytes: (length: number): number[] => { 65 | const result: number[] = []; 66 | if (length <= 0x7f) { 67 | // if the length fits in 7 bits, it's returned as a single byte 68 | result.push(length); 69 | } else { 70 | // otherwise the first byte has a most significant bit of 1 71 | // and the remaining 7 bits indicate how many subsequent bytes 72 | // represent the length. For example: 73 | // 74 | // 82 04 a6 ... 75 | // 76 | // 82 has a leading 1 bit and the value of the next 7 bits is 2 77 | // So the following 2 bytes (04 a6) represent the length 0x04a6 = 1190 bytes 78 | // So then the string occupies the next 1190 bytes after a6 79 | while (length) { 80 | result.push(length & 0xff); 81 | length >>>= 8; 82 | } 83 | result.push(0x80 + result.length); 84 | } 85 | return result.reverse(); 86 | }, 87 | octetString: (octets: Uint8Array): Uint8Array => { 88 | // In DER an octet string starts with the identifier 04, then the length, then the contents 89 | const header = [0x04, ...DER.lengthBytes(octets.byteLength)]; 90 | const result = new Uint8Array(header.length + octets.length); 91 | result.set(header, 0); 92 | result.set(octets, header.length); 93 | return result; 94 | }, 95 | sequence: (...elements: Uint8Array[]): Uint8Array => { 96 | // In DER an sequence starts with the identifier 30, then the length, then the contents 97 | const totalElementLength = elements.reduce((len, i) => len + i.byteLength, 0); 98 | const header = [0x30, ...DER.lengthBytes(totalElementLength)]; 99 | const result = new Uint8Array(header.length + totalElementLength); 100 | result.set(header, 0); 101 | let i = header.length; 102 | for (const elem of elements) { 103 | result.set(elem, i); 104 | i += elem.byteLength; 105 | } 106 | return result; 107 | }, 108 | }; 109 | 110 | export function pkcs1to8(pkcs1: Uint8Array): Uint8Array { 111 | // For RSA at least, a PKCS8 certificate is just a DER sequence 112 | // containing some fields identifying the algorithm as RSA, followed 113 | // by an octet string containing the PKCS1 signature 114 | return DER.sequence(certAndRsa, DER.octetString(pkcs1)); 115 | } 116 | -------------------------------------------------------------------------------- /src/version.ts: -------------------------------------------------------------------------------- 1 | export const VERSION = '11.1.0'; // x-release-please-version 2 | -------------------------------------------------------------------------------- /tests/api-resources/data/annotations.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource annotations', () => { 13 | test('create: only required params', async () => { 14 | const responsePromise = client.data.annotations.create({ date: 1745438400, note: 'This is a note' }); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('create: required and optional params', async () => { 25 | const response = await client.data.annotations.create({ 26 | date: 1745438400, 27 | note: 'This is a note', 28 | sub_property_id: '123456', 29 | }); 30 | }); 31 | 32 | test('retrieve', async () => { 33 | const responsePromise = client.data.annotations.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 34 | const rawResponse = await responsePromise.asResponse(); 35 | expect(rawResponse).toBeInstanceOf(Response); 36 | const response = await responsePromise; 37 | expect(response).not.toBeInstanceOf(Response); 38 | const dataAndResponse = await responsePromise.withResponse(); 39 | expect(dataAndResponse.data).toBe(response); 40 | expect(dataAndResponse.response).toBe(rawResponse); 41 | }); 42 | 43 | test('retrieve: request options instead of params are passed correctly', async () => { 44 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 45 | await expect( 46 | client.data.annotations.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { 47 | path: '/_stainless_unknown_path', 48 | }), 49 | ).rejects.toThrow(Mux.NotFoundError); 50 | }); 51 | 52 | test('update: only required params', async () => { 53 | const responsePromise = client.data.annotations.update('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { 54 | date: 1745438400, 55 | note: 'This is a note', 56 | }); 57 | const rawResponse = await responsePromise.asResponse(); 58 | expect(rawResponse).toBeInstanceOf(Response); 59 | const response = await responsePromise; 60 | expect(response).not.toBeInstanceOf(Response); 61 | const dataAndResponse = await responsePromise.withResponse(); 62 | expect(dataAndResponse.data).toBe(response); 63 | expect(dataAndResponse.response).toBe(rawResponse); 64 | }); 65 | 66 | test('update: required and optional params', async () => { 67 | const response = await client.data.annotations.update('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { 68 | date: 1745438400, 69 | note: 'This is a note', 70 | sub_property_id: '123456', 71 | }); 72 | }); 73 | 74 | test('list', async () => { 75 | const responsePromise = client.data.annotations.list(); 76 | const rawResponse = await responsePromise.asResponse(); 77 | expect(rawResponse).toBeInstanceOf(Response); 78 | const response = await responsePromise; 79 | expect(response).not.toBeInstanceOf(Response); 80 | const dataAndResponse = await responsePromise.withResponse(); 81 | expect(dataAndResponse.data).toBe(response); 82 | expect(dataAndResponse.response).toBe(rawResponse); 83 | }); 84 | 85 | test('list: request options instead of params are passed correctly', async () => { 86 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 87 | await expect(client.data.annotations.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 88 | Mux.NotFoundError, 89 | ); 90 | }); 91 | 92 | test('list: request options and params are passed correctly', async () => { 93 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 94 | await expect( 95 | client.data.annotations.list( 96 | { limit: 0, order_direction: 'asc', page: 0, timeframe: ['string'] }, 97 | { path: '/_stainless_unknown_path' }, 98 | ), 99 | ).rejects.toThrow(Mux.NotFoundError); 100 | }); 101 | 102 | test('delete', async () => { 103 | const responsePromise = client.data.annotations.delete('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); 104 | const rawResponse = await responsePromise.asResponse(); 105 | expect(rawResponse).toBeInstanceOf(Response); 106 | const response = await responsePromise; 107 | expect(response).not.toBeInstanceOf(Response); 108 | const dataAndResponse = await responsePromise.withResponse(); 109 | expect(dataAndResponse.data).toBe(response); 110 | expect(dataAndResponse.response).toBe(rawResponse); 111 | }); 112 | 113 | test('delete: request options instead of params are passed correctly', async () => { 114 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 115 | await expect( 116 | client.data.annotations.delete('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { 117 | path: '/_stainless_unknown_path', 118 | }), 119 | ).rejects.toThrow(Mux.NotFoundError); 120 | }); 121 | }); 122 | -------------------------------------------------------------------------------- /tests/api-resources/data/dimensions.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource dimensions', () => { 13 | test('list', async () => { 14 | const responsePromise = client.data.dimensions.list(); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('list: request options instead of params are passed correctly', async () => { 25 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 26 | await expect(client.data.dimensions.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 27 | Mux.NotFoundError, 28 | ); 29 | }); 30 | 31 | test('listValues', async () => { 32 | const responsePromise = client.data.dimensions.listValues('abcd1234'); 33 | const rawResponse = await responsePromise.asResponse(); 34 | expect(rawResponse).toBeInstanceOf(Response); 35 | const response = await responsePromise; 36 | expect(response).not.toBeInstanceOf(Response); 37 | const dataAndResponse = await responsePromise.withResponse(); 38 | expect(dataAndResponse.data).toBe(response); 39 | expect(dataAndResponse.response).toBe(rawResponse); 40 | }); 41 | 42 | test('listValues: request options instead of params are passed correctly', async () => { 43 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 44 | await expect( 45 | client.data.dimensions.listValues('abcd1234', { path: '/_stainless_unknown_path' }), 46 | ).rejects.toThrow(Mux.NotFoundError); 47 | }); 48 | 49 | test('listValues: request options and params are passed correctly', async () => { 50 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 51 | await expect( 52 | client.data.dimensions.listValues( 53 | 'abcd1234', 54 | { filters: ['string'], limit: 0, metric_filters: ['string'], page: 0, timeframe: ['string'] }, 55 | { path: '/_stainless_unknown_path' }, 56 | ), 57 | ).rejects.toThrow(Mux.NotFoundError); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /tests/api-resources/data/errors.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource errors', () => { 13 | test('list', async () => { 14 | const responsePromise = client.data.errors.list(); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('list: request options instead of params are passed correctly', async () => { 25 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 26 | await expect(client.data.errors.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 27 | Mux.NotFoundError, 28 | ); 29 | }); 30 | 31 | test('list: request options and params are passed correctly', async () => { 32 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 33 | await expect( 34 | client.data.errors.list( 35 | { filters: ['string'], metric_filters: ['string'], timeframe: ['string'] }, 36 | { path: '/_stainless_unknown_path' }, 37 | ), 38 | ).rejects.toThrow(Mux.NotFoundError); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /tests/api-resources/data/exports.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource exports', () => { 13 | test('listVideoViews', async () => { 14 | const responsePromise = client.data.exports.listVideoViews(); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('listVideoViews: request options instead of params are passed correctly', async () => { 25 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 26 | await expect(client.data.exports.listVideoViews({ path: '/_stainless_unknown_path' })).rejects.toThrow( 27 | Mux.NotFoundError, 28 | ); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /tests/api-resources/data/filters.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource filters', () => { 13 | test('listValues', async () => { 14 | const responsePromise = client.data.filters.listValues('abcd1234'); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('listValues: request options instead of params are passed correctly', async () => { 25 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 26 | await expect( 27 | client.data.filters.listValues('abcd1234', { path: '/_stainless_unknown_path' }), 28 | ).rejects.toThrow(Mux.NotFoundError); 29 | }); 30 | 31 | test('listValues: request options and params are passed correctly', async () => { 32 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 33 | await expect( 34 | client.data.filters.listValues( 35 | 'abcd1234', 36 | { filters: ['string'], limit: 0, page: 0, timeframe: ['string'] }, 37 | { path: '/_stainless_unknown_path' }, 38 | ), 39 | ).rejects.toThrow(Mux.NotFoundError); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /tests/api-resources/data/incidents.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource incidents', () => { 13 | test('retrieve', async () => { 14 | const responsePromise = client.data.incidents.retrieve('abcd1234'); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('retrieve: request options instead of params are passed correctly', async () => { 25 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 26 | await expect( 27 | client.data.incidents.retrieve('abcd1234', { path: '/_stainless_unknown_path' }), 28 | ).rejects.toThrow(Mux.NotFoundError); 29 | }); 30 | 31 | test('list', async () => { 32 | const responsePromise = client.data.incidents.list(); 33 | const rawResponse = await responsePromise.asResponse(); 34 | expect(rawResponse).toBeInstanceOf(Response); 35 | const response = await responsePromise; 36 | expect(response).not.toBeInstanceOf(Response); 37 | const dataAndResponse = await responsePromise.withResponse(); 38 | expect(dataAndResponse.data).toBe(response); 39 | expect(dataAndResponse.response).toBe(rawResponse); 40 | }); 41 | 42 | test('list: request options instead of params are passed correctly', async () => { 43 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 44 | await expect(client.data.incidents.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 45 | Mux.NotFoundError, 46 | ); 47 | }); 48 | 49 | test('list: request options and params are passed correctly', async () => { 50 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 51 | await expect( 52 | client.data.incidents.list( 53 | { 54 | limit: 0, 55 | order_by: 'negative_impact', 56 | order_direction: 'asc', 57 | page: 0, 58 | severity: 'warning', 59 | status: 'open', 60 | }, 61 | { path: '/_stainless_unknown_path' }, 62 | ), 63 | ).rejects.toThrow(Mux.NotFoundError); 64 | }); 65 | 66 | test('listRelated', async () => { 67 | const responsePromise = client.data.incidents.listRelated('abcd1234'); 68 | const rawResponse = await responsePromise.asResponse(); 69 | expect(rawResponse).toBeInstanceOf(Response); 70 | const response = await responsePromise; 71 | expect(response).not.toBeInstanceOf(Response); 72 | const dataAndResponse = await responsePromise.withResponse(); 73 | expect(dataAndResponse.data).toBe(response); 74 | expect(dataAndResponse.response).toBe(rawResponse); 75 | }); 76 | 77 | test('listRelated: request options instead of params are passed correctly', async () => { 78 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 79 | await expect( 80 | client.data.incidents.listRelated('abcd1234', { path: '/_stainless_unknown_path' }), 81 | ).rejects.toThrow(Mux.NotFoundError); 82 | }); 83 | 84 | test('listRelated: request options and params are passed correctly', async () => { 85 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 86 | await expect( 87 | client.data.incidents.listRelated( 88 | 'abcd1234', 89 | { limit: 0, order_by: 'negative_impact', order_direction: 'asc', page: 0 }, 90 | { path: '/_stainless_unknown_path' }, 91 | ), 92 | ).rejects.toThrow(Mux.NotFoundError); 93 | }); 94 | }); 95 | -------------------------------------------------------------------------------- /tests/api-resources/data/monitoring/monitoring.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource monitoring', () => { 13 | test('listDimensions', async () => { 14 | const responsePromise = client.data.monitoring.listDimensions(); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('listDimensions: request options instead of params are passed correctly', async () => { 25 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 26 | await expect(client.data.monitoring.listDimensions({ path: '/_stainless_unknown_path' })).rejects.toThrow( 27 | Mux.NotFoundError, 28 | ); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /tests/api-resources/data/video-views.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource videoViews', () => { 13 | test('retrieve', async () => { 14 | const responsePromise = client.data.videoViews.retrieve('abcd1234'); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('retrieve: request options instead of params are passed correctly', async () => { 25 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 26 | await expect( 27 | client.data.videoViews.retrieve('abcd1234', { path: '/_stainless_unknown_path' }), 28 | ).rejects.toThrow(Mux.NotFoundError); 29 | }); 30 | 31 | test('list', async () => { 32 | const responsePromise = client.data.videoViews.list(); 33 | const rawResponse = await responsePromise.asResponse(); 34 | expect(rawResponse).toBeInstanceOf(Response); 35 | const response = await responsePromise; 36 | expect(response).not.toBeInstanceOf(Response); 37 | const dataAndResponse = await responsePromise.withResponse(); 38 | expect(dataAndResponse.data).toBe(response); 39 | expect(dataAndResponse.response).toBe(rawResponse); 40 | }); 41 | 42 | test('list: request options instead of params are passed correctly', async () => { 43 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 44 | await expect(client.data.videoViews.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 45 | Mux.NotFoundError, 46 | ); 47 | }); 48 | 49 | test('list: request options and params are passed correctly', async () => { 50 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 51 | await expect( 52 | client.data.videoViews.list( 53 | { 54 | error_id: 0, 55 | filters: ['string'], 56 | limit: 0, 57 | metric_filters: ['string'], 58 | order_direction: 'asc', 59 | page: 0, 60 | timeframe: ['string'], 61 | viewer_id: 'viewer_id', 62 | }, 63 | { path: '/_stainless_unknown_path' }, 64 | ), 65 | ).rejects.toThrow(Mux.NotFoundError); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /tests/api-resources/rsaPrivateKey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIJKQIBAAKCAgEAsQKUSKmkEKyjMvk+kTq+AMiAo2eRNbEHEf1kMnwXK50HXPnB 3 | ssPWIg7urrdudEv8YI5QRVcbryJeGaqjKPiaPb4Q6bAn4LrJYNG4uop/ymHleIMC 4 | EXDBicsSHxEjHyJdtTl0GmD7nNy0Jeu6Y+YmI654mcih/1x0h46vNOsIXjIciak+ 5 | z18Fvgn0kTyhABehPoP4T0xA2sx7fEm5G5/RCGTUXvmJztaW2Bsne8r/IMdj658A 6 | FO+S/NI0pumQ6ZmGRkZI64sdXdWZlhPy6mqEGt/Yc9HACBcxCp+T3DNl6JcFCETX 7 | ooMBrAOgtQ7BpRtQO4D+8xk1DEwg1k8ei90B3413JwTWGuWBwZUrdkGLd199k9eI 8 | cQV9kKgBTTkn43/zxPrjrsK6kdQdMJwcEdbJOL9+k8NnWvmc2m22oicoY+FV4wZv 9 | Ln0XjfNTJc0aKH5/YpXs6QAoVzLwDhX1Szc9Zd1/p5/4ir89YS6FaFokAB5W3VTh 10 | ldzG8YMgdF6x4DDb9g0Ur8qvG4us622MGAeAfI/D2fiJeEhJvKmpMaMtKNO7ZymC 11 | +oPJtT8K85DFgpiLr799CFU95Knoz8Xil5GTthIZFD494Afo8tSDcznvOQh5Si2B 12 | UgSxpSyflpwKZSG1LkJ4x7Jw+ClqEjlGmz8PziYqktJT7LrthiaigEih6gMCAwEA 13 | AQKCAgADbL1Zuo6GFBEER3ZCcRSEB10VzEcu9sHgQzrRDz2ThnJCBkMNJmTaO9e6 14 | YaotbdrwM1CyRsEuXkfbz0Vg4Y56a1cAbnwXCQYkbWpZkZxvWf2Km15K4BeehuNO 15 | 3pIDZDLT8sygRggYPNzvbuQoUqeiQRnsP8mCm1NV3BjfuTxsNiP/NdsVQA1oY+Dr 16 | fnTO/6YLA5qmTh9jHFm3SeXe9vSgaPMC82kLK3O3sq7M4lyVUcZJJMZnoUsCwT5r 17 | jFFVc7b5XRrEE+j5i8xw7ungRzdPHc2eUAybG3fDcNr3g7cRDPr38f0KE+bQYTGW 18 | zzZH74NZ42ELaw1vs3lfLCC3LAuBM4nB9+P0mWv4YHBloWWSwcPaDWKdZ6/mb/k2 19 | AA/p7WBfwuV3RS82GoeYBDCFR2PHxmCk1ueLiy7FcOLAacHKthVBL0+54Uyq2Ie9 20 | ImELW2qQPy8G6ZyKXQb5g3AiIRA+xf3UuVShsuuWUeo/jUFUkj1wo14j3xP/18Px 21 | 4ksIQFDx+NFuGQrveFUNbgKuhQ97F+1tXlp4SFuF7p//HZT8P4o+DrbdvVZrdACW 22 | 8BwzgZ5cF6+Bhy7jfodTR43RSpGXZQ19kidjlR/+jqY5JvnnkuMwFoCsw6JlIOPI 23 | UC25Kx+YAcYOsfOeHAmcYwby55T3Et9nNQqNd8vsDgs+SmDzQQKCAQEA227e8Ddx 24 | 6AighE+ze3fXCP9VcBZOjzBs/OWaxgs1QjjvgpEaxj2I+nG423J+1DOOBJj8udho 25 | ls3ePwZSwainNMPgDjUi0BA6x4PIWmxSDqUVcGDawYkrudhpA7IvxLG3nir7eYs9 26 | axuDQFQsdsRw3NZ6bnxzJTvqRuB7IqW7JURE5ACTHQkmuKGF8O4FHRL4Zpx3wlXF 27 | SnYUtRNpv9gi36q4fDYxlO+le5LaDd6Za53AjFdaElBSnWjO63HEkBcixR6AHdZX 28 | gZt6PXAc7CVSpmbfS6VKSyyfRGoLczVzU3c7aGs3mAWOA/jZV9wFlkuWIKb5tv1D 29 | n7yaamCS32A66QKCAQEAzoHrr0j1bmsJkExnJ/QZm2rmIQ1ut3N5S+LExEpPfq2u 30 | 2pk09yRYcsP9C6h4YNtJYsl7q81xbnRpRhHDlYIQr866LIjybyOPf0aMqsToHEkB 31 | sJiNtkCwZ9z8nAY5FgDPtrqvjLb8qXmkSiQERBqMHME374ZmTpW+mfiTB17PkwXe 32 | B0gD87LGIhS7R0uYN4z6/j9ZX2uya7IVWfMbjoRM6d8ZFUpFQf/blwtKocN0hJPy 33 | 0yCXG0Xc3eYzJiGC+nGuOWsb3swhDUCdNGTxHYZbUiuouVOy3geyEGdewD524kcB 34 | 62cbz6f4WS7qatZou13twfxQVe+XrEXym0nvgaMSCwKCAQEAyiSPwXECQMO5w0l8 35 | yS/z6zj0pwYVprjwneSSOQDYNkIm+fvcU2Uai8Q5jAckqS05FiktH7MpXksWAq87 36 | i2VnaydKfywZ/twEmglfh1UkHpObdWP0AbfwjQq8awg6ExO4WD+2XBiWItY8igVA 37 | 1MRQSFBYhvGkTVetkU94f8l25nTGldelrmjgv9MkhXdvRIJWTIi1llPXJKo0lz7j 38 | +zQLpEosG1j9QfumUXlN4NsAMHApkd9ifV57TMDhZWnvruFxSW+4jEQJZr8o0/I0 39 | 4qHbSqmX6KLDFw9rROX/2EkUDX7YPnAOzb/IPQaAifyJNRQ6n6fSgO0836kqAvcm 40 | Nhr7CQKCAQA8oBe5Fgo3qGTeYA/Iwvjhj7iP64mdgeESTjjGB6re3c5/jormI110 41 | E+WuDn+Ir9gTkGMmROIQM0zUrVJmChEsC9zMRkgmKKJwEx4o5DXgV+6PEbpIzyT6 42 | 2P2wMIOB2isg0h3HidETUArTWU+HTuPjbTYms6ZFW+DhAwDnIQZ/ezF7ocDHQqy4 43 | RK3WeHLvnAvzqFVslgmDZHywM5bbeCu8XSrX/T3n6l1lMoNuihsi8OxQ3zh9YT0+ 44 | R96sSxpQvB8R7Ef6WKM7aMS+JQRETrVwojCed9wDIu87sZ03gx8TvxTpLxQTGpTm 45 | WceoJdoJZ8HtOU28bOJySPa4cDRIMr+RAoIBAQCtfKAiOcVcFwjYVFS6nlnk5O4b 46 | RUTYAWYRZ3gb0gfxAFvC4eMCD5FGg2bcuQkKx4Z6YqCWtQJoQe7ghFxYBeT0b6XP 47 | H/3EbPKpM70sX5MPPx2Z+8hva61+AAcHaZkPrCDszNsQxK2XD2Ti4+piseYbusKP 48 | dFrNNU/pLPh0fdvQKjsrCzbxktfcHljO25sRXqyhORDYFnNgjzqMnUYv6yFs0uH6 49 | BbtbsmvA6XGqXcU5u5L0bAjG3AwPPiS8o9Y2Q3tBbJVBQDuO2Lbu8Xi/xDzRVQnr 50 | vUAqddLNPeqzR3+SJng+BL9XbUQM4/gvMIpoYtV6In0fLpQZmPf5FEGmcp2w 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /tests/api-resources/system/signing-keys.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource signingKeys', () => { 13 | test('create', async () => { 14 | const responsePromise = client.system.signingKeys.create(); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('create: request options instead of params are passed correctly', async () => { 25 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 26 | await expect(client.system.signingKeys.create({ path: '/_stainless_unknown_path' })).rejects.toThrow( 27 | Mux.NotFoundError, 28 | ); 29 | }); 30 | 31 | test('retrieve', async () => { 32 | const responsePromise = client.system.signingKeys.retrieve('SIGNING_KEY_ID'); 33 | const rawResponse = await responsePromise.asResponse(); 34 | expect(rawResponse).toBeInstanceOf(Response); 35 | const response = await responsePromise; 36 | expect(response).not.toBeInstanceOf(Response); 37 | const dataAndResponse = await responsePromise.withResponse(); 38 | expect(dataAndResponse.data).toBe(response); 39 | expect(dataAndResponse.response).toBe(rawResponse); 40 | }); 41 | 42 | test('retrieve: request options instead of params are passed correctly', async () => { 43 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 44 | await expect( 45 | client.system.signingKeys.retrieve('SIGNING_KEY_ID', { path: '/_stainless_unknown_path' }), 46 | ).rejects.toThrow(Mux.NotFoundError); 47 | }); 48 | 49 | test('list', async () => { 50 | const responsePromise = client.system.signingKeys.list(); 51 | const rawResponse = await responsePromise.asResponse(); 52 | expect(rawResponse).toBeInstanceOf(Response); 53 | const response = await responsePromise; 54 | expect(response).not.toBeInstanceOf(Response); 55 | const dataAndResponse = await responsePromise.withResponse(); 56 | expect(dataAndResponse.data).toBe(response); 57 | expect(dataAndResponse.response).toBe(rawResponse); 58 | }); 59 | 60 | test('list: request options instead of params are passed correctly', async () => { 61 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 62 | await expect(client.system.signingKeys.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 63 | Mux.NotFoundError, 64 | ); 65 | }); 66 | 67 | test('list: request options and params are passed correctly', async () => { 68 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 69 | await expect( 70 | client.system.signingKeys.list({ limit: 0, page: 0 }, { path: '/_stainless_unknown_path' }), 71 | ).rejects.toThrow(Mux.NotFoundError); 72 | }); 73 | 74 | test('delete', async () => { 75 | const responsePromise = client.system.signingKeys.delete('SIGNING_KEY_ID'); 76 | const rawResponse = await responsePromise.asResponse(); 77 | expect(rawResponse).toBeInstanceOf(Response); 78 | const response = await responsePromise; 79 | expect(response).not.toBeInstanceOf(Response); 80 | const dataAndResponse = await responsePromise.withResponse(); 81 | expect(dataAndResponse.data).toBe(response); 82 | expect(dataAndResponse.response).toBe(rawResponse); 83 | }); 84 | 85 | test('delete: request options instead of params are passed correctly', async () => { 86 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 87 | await expect( 88 | client.system.signingKeys.delete('SIGNING_KEY_ID', { path: '/_stainless_unknown_path' }), 89 | ).rejects.toThrow(Mux.NotFoundError); 90 | }); 91 | }); 92 | -------------------------------------------------------------------------------- /tests/api-resources/video/delivery-usage.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource deliveryUsage', () => { 13 | test('list', async () => { 14 | const responsePromise = client.video.deliveryUsage.list(); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('list: request options instead of params are passed correctly', async () => { 25 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 26 | await expect(client.video.deliveryUsage.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 27 | Mux.NotFoundError, 28 | ); 29 | }); 30 | 31 | test('list: request options and params are passed correctly', async () => { 32 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 33 | await expect( 34 | client.video.deliveryUsage.list( 35 | { asset_id: 'asset_id', limit: 0, live_stream_id: 'live_stream_id', page: 0, timeframe: ['string'] }, 36 | { path: '/_stainless_unknown_path' }, 37 | ), 38 | ).rejects.toThrow(Mux.NotFoundError); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /tests/api-resources/video/drm-configurations.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource drmConfigurations', () => { 13 | test('retrieve', async () => { 14 | const responsePromise = client.video.drmConfigurations.retrieve('DRM_CONFIGURATION_ID'); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('retrieve: request options instead of params are passed correctly', async () => { 25 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 26 | await expect( 27 | client.video.drmConfigurations.retrieve('DRM_CONFIGURATION_ID', { path: '/_stainless_unknown_path' }), 28 | ).rejects.toThrow(Mux.NotFoundError); 29 | }); 30 | 31 | test('list', async () => { 32 | const responsePromise = client.video.drmConfigurations.list(); 33 | const rawResponse = await responsePromise.asResponse(); 34 | expect(rawResponse).toBeInstanceOf(Response); 35 | const response = await responsePromise; 36 | expect(response).not.toBeInstanceOf(Response); 37 | const dataAndResponse = await responsePromise.withResponse(); 38 | expect(dataAndResponse.data).toBe(response); 39 | expect(dataAndResponse.response).toBe(rawResponse); 40 | }); 41 | 42 | test('list: request options instead of params are passed correctly', async () => { 43 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 44 | await expect(client.video.drmConfigurations.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 45 | Mux.NotFoundError, 46 | ); 47 | }); 48 | 49 | test('list: request options and params are passed correctly', async () => { 50 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 51 | await expect( 52 | client.video.drmConfigurations.list({ limit: 0, page: 0 }, { path: '/_stainless_unknown_path' }), 53 | ).rejects.toThrow(Mux.NotFoundError); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /tests/api-resources/video/playback-ids.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource playbackIds', () => { 13 | test('retrieve', async () => { 14 | const responsePromise = client.video.playbackIds.retrieve('PLAYBACK_ID'); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | test('retrieve: request options instead of params are passed correctly', async () => { 25 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 26 | await expect( 27 | client.video.playbackIds.retrieve('PLAYBACK_ID', { path: '/_stainless_unknown_path' }), 28 | ).rejects.toThrow(Mux.NotFoundError); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /tests/api-resources/video/transcription-vocabularies.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Mux({ 7 | tokenId: 'my token id', 8 | tokenSecret: 'my secret', 9 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 10 | }); 11 | 12 | describe('resource transcriptionVocabularies', () => { 13 | test('create: only required params', async () => { 14 | const responsePromise = client.video.transcriptionVocabularies.create({ 15 | phrases: ['Mux', 'Live Stream', 'Playback ID', 'video encoding'], 16 | }); 17 | const rawResponse = await responsePromise.asResponse(); 18 | expect(rawResponse).toBeInstanceOf(Response); 19 | const response = await responsePromise; 20 | expect(response).not.toBeInstanceOf(Response); 21 | const dataAndResponse = await responsePromise.withResponse(); 22 | expect(dataAndResponse.data).toBe(response); 23 | expect(dataAndResponse.response).toBe(rawResponse); 24 | }); 25 | 26 | test('create: required and optional params', async () => { 27 | const response = await client.video.transcriptionVocabularies.create({ 28 | phrases: ['Mux', 'Live Stream', 'Playback ID', 'video encoding'], 29 | name: 'Mux API Vocabulary', 30 | passthrough: 'passthrough', 31 | }); 32 | }); 33 | 34 | test('retrieve', async () => { 35 | const responsePromise = client.video.transcriptionVocabularies.retrieve('TRANSCRIPTION_VOCABULARY_ID'); 36 | const rawResponse = await responsePromise.asResponse(); 37 | expect(rawResponse).toBeInstanceOf(Response); 38 | const response = await responsePromise; 39 | expect(response).not.toBeInstanceOf(Response); 40 | const dataAndResponse = await responsePromise.withResponse(); 41 | expect(dataAndResponse.data).toBe(response); 42 | expect(dataAndResponse.response).toBe(rawResponse); 43 | }); 44 | 45 | test('retrieve: request options instead of params are passed correctly', async () => { 46 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 47 | await expect( 48 | client.video.transcriptionVocabularies.retrieve('TRANSCRIPTION_VOCABULARY_ID', { 49 | path: '/_stainless_unknown_path', 50 | }), 51 | ).rejects.toThrow(Mux.NotFoundError); 52 | }); 53 | 54 | test('update: only required params', async () => { 55 | const responsePromise = client.video.transcriptionVocabularies.update('TRANSCRIPTION_VOCABULARY_ID', { 56 | phrases: ['Mux', 'Live Stream', 'RTMP', 'Stream Key'], 57 | }); 58 | const rawResponse = await responsePromise.asResponse(); 59 | expect(rawResponse).toBeInstanceOf(Response); 60 | const response = await responsePromise; 61 | expect(response).not.toBeInstanceOf(Response); 62 | const dataAndResponse = await responsePromise.withResponse(); 63 | expect(dataAndResponse.data).toBe(response); 64 | expect(dataAndResponse.response).toBe(rawResponse); 65 | }); 66 | 67 | test('update: required and optional params', async () => { 68 | const response = await client.video.transcriptionVocabularies.update('TRANSCRIPTION_VOCABULARY_ID', { 69 | phrases: ['Mux', 'Live Stream', 'RTMP', 'Stream Key'], 70 | name: 'Mux API Vocabulary - Updated', 71 | passthrough: 'passthrough', 72 | }); 73 | }); 74 | 75 | test('list', async () => { 76 | const responsePromise = client.video.transcriptionVocabularies.list(); 77 | const rawResponse = await responsePromise.asResponse(); 78 | expect(rawResponse).toBeInstanceOf(Response); 79 | const response = await responsePromise; 80 | expect(response).not.toBeInstanceOf(Response); 81 | const dataAndResponse = await responsePromise.withResponse(); 82 | expect(dataAndResponse.data).toBe(response); 83 | expect(dataAndResponse.response).toBe(rawResponse); 84 | }); 85 | 86 | test('list: request options instead of params are passed correctly', async () => { 87 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 88 | await expect( 89 | client.video.transcriptionVocabularies.list({ path: '/_stainless_unknown_path' }), 90 | ).rejects.toThrow(Mux.NotFoundError); 91 | }); 92 | 93 | test('list: request options and params are passed correctly', async () => { 94 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 95 | await expect( 96 | client.video.transcriptionVocabularies.list( 97 | { limit: 10, page: 0 }, 98 | { path: '/_stainless_unknown_path' }, 99 | ), 100 | ).rejects.toThrow(Mux.NotFoundError); 101 | }); 102 | 103 | test('delete', async () => { 104 | const responsePromise = client.video.transcriptionVocabularies.delete('TRANSCRIPTION_VOCABULARY_ID'); 105 | const rawResponse = await responsePromise.asResponse(); 106 | expect(rawResponse).toBeInstanceOf(Response); 107 | const response = await responsePromise; 108 | expect(response).not.toBeInstanceOf(Response); 109 | const dataAndResponse = await responsePromise.withResponse(); 110 | expect(dataAndResponse.data).toBe(response); 111 | expect(dataAndResponse.response).toBe(rawResponse); 112 | }); 113 | 114 | test('delete: request options instead of params are passed correctly', async () => { 115 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 116 | await expect( 117 | client.video.transcriptionVocabularies.delete('TRANSCRIPTION_VOCABULARY_ID', { 118 | path: '/_stainless_unknown_path', 119 | }), 120 | ).rejects.toThrow(Mux.NotFoundError); 121 | }); 122 | }); 123 | -------------------------------------------------------------------------------- /tests/api-resources/webhooks.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Mux from '@mux/mux-node'; 4 | 5 | const mux = new Mux({ 6 | tokenId: 'my token id', 7 | tokenSecret: 'my secret', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource webhooks', () => { 12 | const payload = '{"test":"body"}'; 13 | const secret = 'SuperSecret123'; 14 | const timestamp = '1565125718'; 15 | const hash = `854ece4c22acef7c66b57d4e504153bc512595e8e9c772ece2a68150548c19a7`; 16 | const signature = `t=${timestamp},v1=${hash}`; 17 | const headers = { 18 | 'mux-signature': signature, 19 | }; 20 | const fakeNow = parseFloat(timestamp) * 1000; 21 | beforeEach(() => { 22 | jest.spyOn(global.Date, 'now').mockImplementation(() => fakeNow); 23 | }); 24 | afterEach(() => { 25 | // restore the spy created with spyOn 26 | jest.restoreAllMocks(); 27 | }); 28 | describe('unwrap', () => { 29 | it('deserializes the payload object', () => { 30 | mux.webhooks.unwrap(payload, headers, secret); 31 | }); 32 | }); 33 | describe('unwrap_times', () => { 34 | const payload = '{"test":{"nested":{"nanos":718234, "seconds":1691711005}}}'; 35 | const secret = 'SuperSecret123'; 36 | const timestamp = '1565125718'; 37 | const hash = `bd315c24bce1c2b8ad325696f26530c8ef7d7d830afb7c1381903705d04607be`; 38 | const signature = `t=${timestamp},v1=${hash}`; 39 | const headers = { 40 | 'mux-signature': signature, 41 | }; 42 | it('deserializes the payload object', () => { 43 | expect(mux.webhooks.unwrap(payload, headers, secret)).toEqual({ 44 | test: { nested: '2023-08-10T23:43:25.718Z' }, 45 | }); 46 | }); 47 | }); 48 | 49 | describe('verifySignature', () => { 50 | it('should pass for valid signature', () => { 51 | mux.webhooks.verifySignature(payload, headers, secret); 52 | }); 53 | 54 | it('should throw for timestamp outside threshold', () => { 55 | jest.spyOn(global.Date, 'now').mockImplementation(() => fakeNow + 360000); // 6 minutes 56 | expect(() => mux.webhooks.verifySignature(payload, headers, secret)).toThrowErrorMatchingInlineSnapshot( 57 | `"Webhook timestamp is too old"`, 58 | ); 59 | }); 60 | 61 | it('should pass for multiple signatures', () => { 62 | mux.webhooks.verifySignature( 63 | payload, 64 | { 65 | ...headers, 66 | 'mux-signature': `t=${timestamp},v1=invalid-sig,v1=${hash}`, 67 | }, 68 | secret, 69 | ); 70 | }); 71 | 72 | it('should throw for different signature version', () => { 73 | expect(() => 74 | mux.webhooks.verifySignature( 75 | payload, 76 | { 77 | ...headers, 78 | 'mux-signature': `t=${timestamp},v2=${hash}`, 79 | }, 80 | secret, 81 | ), 82 | ).toThrowErrorMatchingInlineSnapshot(`"No v1 signatures found"`); 83 | }); 84 | 85 | it('should pass for multiple signatures with different version', () => { 86 | mux.webhooks.verifySignature( 87 | payload, 88 | { 89 | ...headers, 90 | 'mux-signature': `t=${timestamp},v2=${hash},v1=${hash}`, 91 | }, 92 | secret, 93 | ); 94 | }); 95 | 96 | it('should throw if signature timestamp is missing', () => { 97 | expect(() => 98 | mux.webhooks.verifySignature( 99 | payload, 100 | { 101 | ...headers, 102 | 'mux-signature': hash, 103 | }, 104 | secret, 105 | ), 106 | ).toThrowErrorMatchingInlineSnapshot(`"Unable to extract timestamp and signatures from header"`); 107 | }); 108 | 109 | it('should throw if payload is not a string', () => { 110 | expect(() => 111 | mux.webhooks.verifySignature({ payload: 'not a string' } as any, headers, secret), 112 | ).toThrowErrorMatchingInlineSnapshot( 113 | `"Webhook body must be passed as the raw JSON string sent from the server (do not parse it first)."`, 114 | ); 115 | }); 116 | }); 117 | }); 118 | -------------------------------------------------------------------------------- /tests/form.test.ts: -------------------------------------------------------------------------------- 1 | import { multipartFormRequestOptions, createForm } from '@mux/mux-node/core'; 2 | import { Blob } from '@mux/mux-node/_shims/index'; 3 | import { toFile } from '@mux/mux-node'; 4 | 5 | describe('form data validation', () => { 6 | test('valid values do not error', async () => { 7 | await multipartFormRequestOptions({ 8 | body: { 9 | foo: 'foo', 10 | string: 1, 11 | bool: true, 12 | file: await toFile(Buffer.from('some-content')), 13 | blob: new Blob(['Some content'], { type: 'text/plain' }), 14 | }, 15 | }); 16 | }); 17 | 18 | test('null', async () => { 19 | await expect(() => 20 | multipartFormRequestOptions({ 21 | body: { 22 | null: null, 23 | }, 24 | }), 25 | ).rejects.toThrow(TypeError); 26 | }); 27 | 28 | test('undefined is stripped', async () => { 29 | const form = await createForm({ 30 | foo: undefined, 31 | bar: 'baz', 32 | }); 33 | expect(form.has('foo')).toBe(false); 34 | expect(form.get('bar')).toBe('baz'); 35 | }); 36 | 37 | test('nested undefined property is stripped', async () => { 38 | const form = await createForm({ 39 | bar: { 40 | baz: undefined, 41 | }, 42 | }); 43 | expect(Array.from(form.entries())).toEqual([]); 44 | 45 | const form2 = await createForm({ 46 | bar: { 47 | foo: 'string', 48 | baz: undefined, 49 | }, 50 | }); 51 | expect(Array.from(form2.entries())).toEqual([['bar[foo]', 'string']]); 52 | }); 53 | 54 | test('nested undefined array item is stripped', async () => { 55 | const form = await createForm({ 56 | bar: [undefined, undefined], 57 | }); 58 | expect(Array.from(form.entries())).toEqual([]); 59 | 60 | const form2 = await createForm({ 61 | bar: [undefined, 'foo'], 62 | }); 63 | expect(Array.from(form2.entries())).toEqual([['bar[]', 'foo']]); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /tests/responses.test.ts: -------------------------------------------------------------------------------- 1 | import { createResponseHeaders } from '@mux/mux-node/core'; 2 | import { Headers } from '@mux/mux-node/_shims/index'; 3 | 4 | describe('response parsing', () => { 5 | // TODO: test unicode characters 6 | test('headers are case agnostic', async () => { 7 | const headers = createResponseHeaders(new Headers({ 'Content-Type': 'foo', Accept: 'text/plain' })); 8 | expect(headers['content-type']).toEqual('foo'); 9 | expect(headers['Content-type']).toEqual('foo'); 10 | expect(headers['Content-Type']).toEqual('foo'); 11 | expect(headers['accept']).toEqual('text/plain'); 12 | expect(headers['Accept']).toEqual('text/plain'); 13 | expect(headers['Hello-World']).toBeUndefined(); 14 | }); 15 | 16 | test('duplicate headers are concatenated', () => { 17 | const headers = createResponseHeaders( 18 | new Headers([ 19 | ['Content-Type', 'text/xml'], 20 | ['Content-Type', 'application/json'], 21 | ]), 22 | ); 23 | expect(headers['content-type']).toBe('text/xml, application/json'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /tests/stringifyQuery.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { Mux } from '@mux/mux-node'; 4 | 5 | const { stringifyQuery } = Mux.prototype as any; 6 | 7 | describe(stringifyQuery, () => { 8 | for (const [input, expected] of [ 9 | [{ a: '1', b: 2, c: true }, 'a=1&b=2&c=true'], 10 | [{ a: null, b: false, c: undefined }, 'a=&b=false'], 11 | [{ 'a/b': 1.28341 }, `${encodeURIComponent('a/b')}=1.28341`], 12 | [ 13 | { 'a/b': 'c/d', 'e=f': 'g&h' }, 14 | `${encodeURIComponent('a/b')}=${encodeURIComponent('c/d')}&${encodeURIComponent( 15 | 'e=f', 16 | )}=${encodeURIComponent('g&h')}`, 17 | ], 18 | ]) { 19 | it(`${JSON.stringify(input)} -> ${expected}`, () => { 20 | expect(stringifyQuery(input)).toEqual(expected); 21 | }); 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /tests/uploads.test.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { toFile, type ResponseLike } from '@mux/mux-node/uploads'; 3 | import { File } from '@mux/mux-node/_shims/index'; 4 | 5 | class MyClass { 6 | name: string = 'foo'; 7 | } 8 | 9 | function mockResponse({ url, content }: { url: string; content?: Blob }): ResponseLike { 10 | return { 11 | url, 12 | blob: async () => content as any, 13 | }; 14 | } 15 | 16 | describe('toFile', () => { 17 | it('throws a helpful error for mismatched types', async () => { 18 | await expect( 19 | // @ts-expect-error intentionally mismatched type 20 | toFile({ foo: 'string' }), 21 | ).rejects.toThrowErrorMatchingInlineSnapshot( 22 | `"Unexpected data type: object; constructor: Object; props: ["foo"]"`, 23 | ); 24 | 25 | await expect( 26 | // @ts-expect-error intentionally mismatched type 27 | toFile(new MyClass()), 28 | ).rejects.toThrowErrorMatchingInlineSnapshot( 29 | `"Unexpected data type: object; constructor: MyClass; props: ["name"]"`, 30 | ); 31 | }); 32 | 33 | it('disallows string at the type-level', async () => { 34 | // @ts-expect-error we intentionally do not type support for `string` 35 | // to help people avoid passing a file path 36 | const file = await toFile('contents'); 37 | expect(file.text()).resolves.toEqual('contents'); 38 | }); 39 | 40 | it('extracts a file name from a Response', async () => { 41 | const response = mockResponse({ url: 'https://example.com/my/audio.mp3' }); 42 | const file = await toFile(response); 43 | expect(file.name).toEqual('audio.mp3'); 44 | }); 45 | 46 | it('extracts a file name from a File', async () => { 47 | const input = new File(['foo'], 'input.jsonl'); 48 | const file = await toFile(input); 49 | expect(file.name).toEqual('input.jsonl'); 50 | }); 51 | 52 | it('extracts a file name from a ReadStream', async () => { 53 | const input = fs.createReadStream('tests/uploads.test.ts'); 54 | const file = await toFile(input); 55 | expect(file.name).toEqual('uploads.test.ts'); 56 | }); 57 | 58 | it('does not copy File objects', async () => { 59 | const input = new File(['foo'], 'input.jsonl', { type: 'jsonl' }); 60 | const file = await toFile(input); 61 | expect(file).toBe(input); 62 | expect(file.name).toEqual('input.jsonl'); 63 | expect(file.type).toBe('jsonl'); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /tsc-multi.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { "extname": ".js", "module": "commonjs" }, 4 | { "extname": ".mjs", "module": "esnext" } 5 | ], 6 | "projects": ["tsconfig.build.json"] 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["dist/src"], 4 | "exclude": ["dist/src/_shims/*-deno.ts"], 5 | "compilerOptions": { 6 | "rootDir": "./dist/src", 7 | "paths": { 8 | "@mux/mux-node/*": ["dist/src/*"], 9 | "@mux/mux-node": ["dist/src/index.ts"], 10 | }, 11 | "noEmit": false, 12 | "declaration": true, 13 | "declarationMap": true, 14 | "outDir": "dist", 15 | "pretty": true, 16 | "sourceMap": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["dist-deno"], 4 | "exclude": [], 5 | "compilerOptions": { 6 | "rootDir": "./dist-deno", 7 | "lib": ["es2020", "DOM"], 8 | "noEmit": true, 9 | "declaration": true, 10 | "declarationMap": true, 11 | "outDir": "dist-deno", 12 | "pretty": true, 13 | "sourceMap": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.dist-src.json: -------------------------------------------------------------------------------- 1 | { 2 | // this config is included in the published src directory to prevent TS errors 3 | // from appearing when users go to source, and VSCode opens the source .ts file 4 | // via declaration maps 5 | "include": ["index.ts"], 6 | "compilerOptions": { 7 | "target": "es2015", 8 | "lib": ["DOM"], 9 | "moduleResolution": "node" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src", "tests", "examples"], 3 | "exclude": ["src/_shims/**/*-deno.ts"], 4 | "compilerOptions": { 5 | "target": "es2020", 6 | "lib": ["es2020"], 7 | "module": "commonjs", 8 | "moduleResolution": "node", 9 | "esModuleInterop": true, 10 | "baseUrl": "./", 11 | "paths": { 12 | "@mux/mux-node/_shims/auto/*": ["src/_shims/auto/*-node"], 13 | "@mux/mux-node/*": ["src/*"], 14 | "@mux/mux-node": ["src/index.ts"] 15 | }, 16 | "noEmit": true, 17 | 18 | "resolveJsonModule": true, 19 | 20 | "forceConsistentCasingInFileNames": true, 21 | 22 | "strict": true, 23 | "noImplicitAny": true, 24 | "strictNullChecks": true, 25 | "strictFunctionTypes": true, 26 | "strictBindCallApply": true, 27 | "strictPropertyInitialization": true, 28 | "noImplicitThis": true, 29 | "noImplicitReturns": true, 30 | "alwaysStrict": true, 31 | "exactOptionalPropertyTypes": true, 32 | "noUncheckedIndexedAccess": true, 33 | "noImplicitOverride": true, 34 | "noPropertyAccessFromIndexSignature": true, 35 | "isolatedModules": false, 36 | 37 | "skipLibCheck": true 38 | } 39 | } 40 | --------------------------------------------------------------------------------