Full Code of vitalik/django-ninja for AI

master 0b67d47637a9 cached
279 files
3.4 MB
895.9k tokens
6169 symbols
1 requests
Download .txt
Showing preview only (3,579K chars total). Download the full file or copy to clipboard to get everything.
Repository: vitalik/django-ninja
Branch: master
Commit: 0b67d47637a9
Files: 279
Total size: 3.4 MB

Directory structure:
gitextract_4zhr2mua/

├── .dockerignore
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── feature_request.md
│   │   └── question.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── close-old-issues.yml
│       ├── docs.yml
│       ├── publish.yml
│       ├── test.yml
│       └── test_full.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── docs/
│   ├── docs/
│   │   ├── chat.md
│   │   ├── extra.css
│   │   ├── guides/
│   │   │   ├── api-docs.md
│   │   │   ├── async-support.md
│   │   │   ├── authentication.md
│   │   │   ├── decorators.md
│   │   │   ├── errors.md
│   │   │   ├── input/
│   │   │   │   ├── body.md
│   │   │   │   ├── file-params.md
│   │   │   │   ├── filtering.md
│   │   │   │   ├── form-params.md
│   │   │   │   ├── operations.md
│   │   │   │   ├── path-params.md
│   │   │   │   ├── query-params.md
│   │   │   │   └── request-parsers.md
│   │   │   ├── response/
│   │   │   │   ├── config-pydantic.md
│   │   │   │   ├── django-pydantic-create-schema.md
│   │   │   │   ├── django-pydantic.md
│   │   │   │   ├── index.md
│   │   │   │   ├── pagination.md
│   │   │   │   ├── response-renderers.md
│   │   │   │   └── temporal_response.md
│   │   │   ├── routers.md
│   │   │   ├── testing.md
│   │   │   ├── throttling.md
│   │   │   ├── urls.md
│   │   │   └── versioning.md
│   │   ├── help.md
│   │   ├── index.md
│   │   ├── javascripts/
│   │   │   └── ask-ai-button.js
│   │   ├── motivation.md
│   │   ├── proposals/
│   │   │   ├── cbv.md
│   │   │   ├── index.md
│   │   │   └── v1.md
│   │   ├── reference/
│   │   │   ├── api.md
│   │   │   ├── csrf.md
│   │   │   ├── management-commands.md
│   │   │   ├── operations-parameters.md
│   │   │   └── settings.md
│   │   ├── releases.md
│   │   ├── tutorial/
│   │   │   ├── index.md
│   │   │   ├── other/
│   │   │   │   ├── crud.md
│   │   │   │   └── video.md
│   │   │   ├── step2.md
│   │   │   └── step3.md
│   │   └── whatsnew_v1.md
│   ├── mkdocs.yml
│   ├── requirements.txt
│   └── src/
│       ├── index001.py
│       └── tutorial/
│           ├── authentication/
│           │   ├── apikey01.py
│           │   ├── apikey02.py
│           │   ├── apikey03.py
│           │   ├── basic01.py
│           │   ├── bearer01.py
│           │   ├── bearer02.py
│           │   ├── code001.py
│           │   ├── code002.py
│           │   ├── global01.py
│           │   ├── multiple01.py
│           │   └── schema01.py
│           ├── body/
│           │   ├── code01.py
│           │   ├── code02.py
│           │   └── code03.py
│           ├── form/
│           │   ├── code01.py
│           │   ├── code02.py
│           │   └── code03.py
│           ├── path/
│           │   ├── code01.py
│           │   ├── code010.py
│           │   └── code02.py
│           └── query/
│               ├── code01.py
│               ├── code010.py
│               ├── code02.py
│               └── code03.py
├── mypy.ini
├── ninja/
│   ├── __init__.py
│   ├── compatibility/
│   │   ├── __init__.py
│   │   ├── files.py
│   │   ├── streaming.py
│   │   └── util.py
│   ├── conf.py
│   ├── constants.py
│   ├── decorators.py
│   ├── errors.py
│   ├── files.py
│   ├── filter_schema.py
│   ├── main.py
│   ├── management/
│   │   ├── __init__.py
│   │   ├── commands/
│   │   │   ├── __init__.py
│   │   │   └── export_openapi_schema.py
│   │   └── utils.py
│   ├── openapi/
│   │   ├── __init__.py
│   │   ├── docs.py
│   │   ├── schema.py
│   │   ├── urls.py
│   │   └── views.py
│   ├── operation.py
│   ├── orm/
│   │   ├── __init__.py
│   │   ├── factory.py
│   │   ├── fields.py
│   │   ├── metaclass.py
│   │   └── shortcuts.py
│   ├── pagination.py
│   ├── params/
│   │   ├── __init__.py
│   │   ├── functions.py
│   │   └── models.py
│   ├── parser.py
│   ├── patch_dict.py
│   ├── py.typed
│   ├── renderers.py
│   ├── responses.py
│   ├── router.py
│   ├── schema.py
│   ├── security/
│   │   ├── __init__.py
│   │   ├── apikey.py
│   │   ├── base.py
│   │   ├── http.py
│   │   └── session.py
│   ├── signature/
│   │   ├── __init__.py
│   │   ├── details.py
│   │   └── utils.py
│   ├── static/
│   │   └── ninja/
│   │       ├── redoc.standalone.js
│   │       ├── swagger-ui-bundle.js
│   │       ├── swagger-ui-init.js
│   │       └── swagger-ui.css
│   ├── streaming.py
│   ├── templates/
│   │   └── ninja/
│   │       ├── favicons.html
│   │       ├── redoc.html
│   │       ├── redoc_cdn.html
│   │       ├── swagger.html
│   │       └── swagger_cdn.html
│   ├── testing/
│   │   ├── __init__.py
│   │   └── client.py
│   ├── throttling.py
│   ├── types.py
│   └── utils.py
├── pyproject.toml
├── scripts/
│   └── build-docs.sh
└── tests/
    ├── conftest.py
    ├── demo_project/
    │   ├── db.sqlite3
    │   ├── demo/
    │   │   ├── __init__.py
    │   │   ├── asgi.py
    │   │   ├── settings.py
    │   │   ├── urls.py
    │   │   └── wsgi.py
    │   ├── manage.py
    │   ├── multi_param/
    │   │   ├── __init__.py
    │   │   ├── api.py
    │   │   ├── asgi.py
    │   │   ├── manage.py
    │   │   ├── settings.py
    │   │   ├── urls.py
    │   │   └── wsgi.py
    │   └── someapp/
    │       ├── __init__.py
    │       ├── admin.py
    │       ├── api.py
    │       ├── models.py
    │       └── views.py
    ├── env-matrix/
    │   ├── Dockerfile
    │   ├── Dockerfile.backup
    │   ├── README.md
    │   ├── create_docker.py
    │   ├── docker-compose.yml
    │   ├── install_env.sh
    │   └── run.sh
    ├── main.py
    ├── mypy_test.py
    ├── pytest.ini
    ├── test_add_decorator.py
    ├── test_add_decorator_async.py
    ├── test_alias.py
    ├── test_annotated.py
    ├── test_api_instance.py
    ├── test_app.py
    ├── test_async.py
    ├── test_auth.py
    ├── test_auth_async.py
    ├── test_auth_global.py
    ├── test_auth_inheritance_routers.py
    ├── test_auth_routers.py
    ├── test_body.py
    ├── test_compatibility.py
    ├── test_conf.py
    ├── test_csrf.py
    ├── test_csrf_async.py
    ├── test_decorators.py
    ├── test_discriminator.py
    ├── test_django_models.py
    ├── test_docs/
    │   ├── __init__.py
    │   ├── test_auth.py
    │   ├── test_body.py
    │   ├── test_form.py
    │   ├── test_index.py
    │   ├── test_path.py
    │   └── test_query.py
    ├── test_enum.py
    ├── test_errors.py
    ├── test_exceptions.py
    ├── test_export_openapi_schema.py
    ├── test_files.py
    ├── test_filter_schema.py
    ├── test_forms.py
    ├── test_forms_and_files.py
    ├── test_inheritance_routers.py
    ├── test_lists.py
    ├── test_misc.py
    ├── test_models.py
    ├── test_openapi_docs.py
    ├── test_openapi_extra.py
    ├── test_openapi_params.py
    ├── test_openapi_schema.py
    ├── test_orm_metaclass.py
    ├── test_orm_relations.py
    ├── test_orm_schemas.py
    ├── test_pagination.py
    ├── test_pagination_async.py
    ├── test_pagination_cursor.py
    ├── test_pagination_router.py
    ├── test_params_models.py
    ├── test_parser.py
    ├── test_patch_dict.py
    ├── test_path.py
    ├── test_pydantic_migrate.py
    ├── test_query.py
    ├── test_query_schema.py
    ├── test_renderer.py
    ├── test_request.py
    ├── test_response.py
    ├── test_response_cookies.py
    ├── test_response_multiple.py
    ├── test_response_params.py
    ├── test_reverse.py
    ├── test_router_add_router.py
    ├── test_router_defaults.py
    ├── test_router_path_params.py
    ├── test_router_reuse.py
    ├── test_schema.py
    ├── test_schema_context.py
    ├── test_serialization_context.py
    ├── test_server.py
    ├── test_signature_details.py
    ├── test_status.py
    ├── test_streaming.py
    ├── test_test_client.py
    ├── test_throttling.py
    ├── test_union.py
    ├── test_utils.py
    ├── test_with_django/
    │   ├── __init__.py
    │   ├── schema_fixtures/
    │   │   ├── test-multi-body-file.json
    │   │   ├── test-multi-body-form-file.json
    │   │   ├── test-multi-body-form.json
    │   │   ├── test-multi-body.json
    │   │   ├── test-multi-cookie.json
    │   │   ├── test-multi-form-body-file.json
    │   │   ├── test-multi-form-body.json
    │   │   ├── test-multi-form-file.json
    │   │   ├── test-multi-form.json
    │   │   ├── test-multi-header.json
    │   │   ├── test-multi-path.json
    │   │   └── test-multi-query.json
    │   └── test_multi_param_parsing.py
    ├── test_wraps.py
    └── util.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
*.pyc
.venv*
.vscode
.mypy_cache
.coverage
htmlcov

dist
test.py



================================================
FILE: .github/FUNDING.yml
================================================
# polar: django-ninja
custom: ["https://www.buymeacoffee.com/djangoninja"]


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: "[BUG] "
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**Versions (please complete the following information):**
 - Python version: [e.g. 3.6]
 - Django version: [e.g. 4.0]
 - Django-Ninja version: [e.g. 0.16.2]
 - Pydantic version: [e.g. 1.9.0]

Note you can quickly get this by runninng in `./manage.py shell` this line:
```
import django; import pydantic; import ninja; django.__version__; ninja.__version__; pydantic.__version__
```


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.


================================================
FILE: .github/ISSUE_TEMPLATE/question.md
================================================
---
name: Question
about: Having troubles implementing something ?
title: ''
labels: ''
assignees: ''

---

Please describe what you are trying to achieve

Please include code examples (like models code, schemes code, view function) to help understand the issue


================================================
FILE: .github/dependabot.yml
================================================
version: 2

updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: monthly


================================================
FILE: .github/workflows/close-old-issues.yml
================================================
name: Close Old Issues

on:
  workflow_dispatch:
    inputs:
      days_old:
        description: 'Close issues older than N days'
        required: true
        default: '365'
        type: number
      dry_run:
        description: 'Dry run mode (preview only, do not close)'
        required: true
        default: true
        type: boolean
      comment_on_close:
        description: 'Add comment when closing issues'
        required: true
        default: true
        type: boolean

jobs:
  close-old-issues:
    runs-on: ubuntu-latest
    permissions:
      issues: write

    steps:
      - name: Close or list old issues
        uses: actions/github-script@v8
        with:
          script: |
            const daysOld = ${{ inputs.days_old }};
            const dryRun = ${{ inputs.dry_run }};
            const addComment = ${{ inputs.comment_on_close }};
            const cutoffDate = new Date();
            cutoffDate.setDate(cutoffDate.getDate() - daysOld);

            console.log(`Looking for issues older than ${daysOld} days (before ${cutoffDate.toISOString()})`);
            console.log(`Dry run mode: ${dryRun ? 'YES (no changes will be made)' : 'NO (issues will be closed)'}`);
            console.log('---');

            let page = 1;
            let issuesClosed = 0;
            let issuesToClose = [];

            while (true) {
              const issues = await github.rest.issues.listForRepo({
                owner: context.repo.owner,
                repo: context.repo.repo,
                state: 'open',
                sort: 'created',
                direction: 'asc',
                per_page: 100,
                page: page
              });

              if (issues.data.length === 0) {
                break;
              }

              for (const issue of issues.data) {
                // Skip pull requests
                if (issue.pull_request) {
                  continue;
                }

                const createdAt = new Date(issue.created_at);
                const updatedAt = new Date(issue.updated_at);

                // Check if issue is old enough based on last update
                if (updatedAt < cutoffDate) {
                  const daysOldCalculated = Math.floor((Date.now() - updatedAt.getTime()) / (1000 * 60 * 60 * 24));

                  issuesToClose.push({
                    number: issue.number,
                    title: issue.title,
                    created_at: createdAt.toISOString().split('T')[0],
                    updated_at: updatedAt.toISOString().split('T')[0],
                    days_old: daysOldCalculated,
                    url: issue.html_url
                  });
                }
              }

              page++;
            }

            console.log(`\nFound ${issuesToClose.length} issue(s) to close:\n`);

            for (const issue of issuesToClose) {
              console.log(`#${issue.number}: ${issue.title}`);
              console.log(`  Created: ${issue.created_at}`);
              console.log(`  Last updated: ${issue.updated_at} (${issue.days_old} days ago)`);
              console.log(`  URL: ${issue.url}`);
              console.log('');

              if (!dryRun) {
                try {
                  // Add a comment before closing (if enabled)
                  if (addComment) {
                    await github.rest.issues.createComment({
                      owner: context.repo.owner,
                      repo: context.repo.repo,
                      issue_number: issue.number,
                      body: `This issue has been automatically closed due to inactivity (no updates for ${issue.days_old} days). If you believe this issue is still relevant, please feel free to reopen it or create a new issue.`
                    });
                  }

                  // Close the issue
                  await github.rest.issues.update({
                    owner: context.repo.owner,
                    repo: context.repo.repo,
                    issue_number: issue.number,
                    state: 'closed',
                    state_reason: 'not_planned'
                  });

                  issuesClosed++;
                  console.log(`  ✓ Closed issue #${issue.number}`);
                } catch (error) {
                  console.error(`  ✗ Failed to close issue #${issue.number}: ${error.message}`);
                }
              }
            }

            console.log('\n---');
            if (dryRun) {
              console.log(`DRY RUN: Would close ${issuesToClose.length} issue(s)`);
              console.log('To actually close these issues, run this workflow again with dry_run set to false');
            } else {
              console.log(`Successfully closed ${issuesClosed} out of ${issuesToClose.length} issue(s)`);
            }

            // Set output for summary
            core.summary
              .addHeading(dryRun ? 'Dry Run Results' : 'Close Old Issues Results')
              .addRaw(`**Mode:** ${dryRun ? '🔍 Dry Run (Preview Only)' : '✅ Live Run'}\n`)
              .addRaw(`**Cutoff Date:** Issues last updated before ${cutoffDate.toISOString().split('T')[0]}\n`)
              .addRaw(`**Days Old Threshold:** ${daysOld} days\n`)
              .addRaw(`**Issues ${dryRun ? 'Found' : 'Closed'}:** ${dryRun ? issuesToClose.length : issuesClosed}\n\n`);

            if (issuesToClose.length > 0) {
              core.summary.addHeading('Issues', 3);
              const tableData = issuesToClose.map(issue => [
                `#${issue.number}`,
                issue.title.substring(0, 80) + (issue.title.length > 80 ? '...' : ''),
                issue.updated_at,
                `${issue.days_old} days`,
                `[View](${issue.url})`
              ]);

              core.summary.addTable([
                ['Issue', 'Title', 'Last Updated', 'Age', 'Link'],
                ...tableData
              ]);
            } else {
              core.summary.addRaw('\nNo issues found matching the criteria.');
            }

            await core.summary.write();


================================================
FILE: .github/workflows/docs.yml
================================================
name: Docs

on:
  workflow_dispatch:

jobs:
  docs:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0
      - name: Docs update
        run: git push origin master:docs


================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish

on:
  release:
    types: [published]
  workflow_dispatch:

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Set up Python
        uses: actions/setup-python@v5
      - name: Install Flit
        run: pip install flit
      - name: Install Dependencies
        run: flit install --symlink
      - name: Publish
        env:
          # FLIT_USERNAME: ${{ secrets.FLIT_USERNAME }}
          # FLIT_PASSWORD: ${{ secrets.FLIT_PASSWORD }}
          FLIT_USERNAME: __token__
          FLIT_PASSWORD: ${{ secrets.PYPI_TOKEN }}
        run: flit publish


================================================
FILE: .github/workflows/test.yml
================================================
name: Test Coverage

on:
  push:
    branches:
      - master

jobs:
  test_coverage:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v6
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - name: Install Flit
        run: pip install flit "django>=5.1"
      - name: Install Dependencies
        run: flit install --symlink
      - name: Test
        run: pytest --cov=ninja --cov-report=xml tests
      - name: Coverage
        uses: codecov/codecov-action@v4.4.1


================================================
FILE: .github/workflows/test_full.yml
================================================
name: Full Test

on:
  push:
  workflow_dispatch:
  pull_request:
    types: [assigned, opened, synchronize, reopened]

jobs:
  test:
    runs-on: ubuntu-22.04
    strategy:
      matrix:
        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
        django-version: ['<3.2', '<3.3', '<4.2', '<4.3', '<5.1', '<5.2', '<5.3', '<6.1']
        exclude:
          - python-version: '3.7'
            django-version: '<5.1'
          
          - python-version: '3.8'
            django-version: '<5.1'
          
          - python-version: '3.9'
            django-version: '<5.1'
          
          - python-version: '3.12'
            django-version: '<3.2'
          - python-version: '3.12'
            django-version: '<3.3'
          
          - python-version: '3.13'
            django-version: '<3.2'
          - python-version: '3.13'
            django-version: '<3.3'
          
          # as of oct 2025 looks like django < 5.2 does not support python 3.14
          - python-version: '3.14'
            django-version: '<3.2'
          - python-version: '3.14'
            django-version: '<3.3'
          - python-version: '3.14'
            django-version: '<4.2'
          - python-version: '3.14'
            django-version: '<4.3'
          - python-version: '3.14'
            django-version: '<5.1'
          - python-version: '3.14'
            django-version: '<5.2'
    
    steps:
      - uses: actions/checkout@v6
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install core
        run: pip install "Django${{ matrix.django-version }}" "pydantic<3"
      - name: Install tests
        run: pip install pytest pytest-asyncio pytest-django psycopg2-binary
      - name: Test
        run: pytest

  coverage:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v6
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: 3.12
      - name: Install Flit
        run: pip install flit "django>=5.2"
      - name: Install Dependencies
        run: flit install --symlink
      - name: Test
        run: pytest --cov=ninja

  codestyle:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: 3.12
      - name: Install Flit
        run: pip install flit
      - name: Install Dependencies
        run: flit install --symlink
      - name: Ruff format
        run: ruff format --check ninja tests
      - name: Ruff lint
        run: ruff check ninja tests
      - name: mypy
        run: mypy ninja tests/mypy_test.py


================================================
FILE: .gitignore
================================================
*.pyc
.venv*
.vscode
.mypy_cache
.coverage
htmlcov
/coverage.xml

dist
test.py

docs/site

.DS_Store
.idea
.python-version
*.local.md


================================================
FILE: .pre-commit-config.yaml
================================================
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.2.0
    hooks:
      - id: check-yaml
      # - id: end-of-file-fixer
      # - id: trailing-whitespace
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.7.1
    hooks:
      - id: mypy
        additional_dependencies: ["django-stubs", "pydantic"]
        exclude: (tests|docs)/
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.4.2
    hooks:
      - id: ruff-format
      - id: ruff
        args: [--fix, --exit-non-zero-on-fix]


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

Django Ninja uses Flit to build, package and publish the project.

to install it use:

```
pip install flit
```

Once you have it - to install all dependencies required for development and testing  use this command:


```
flit install --deps develop --symlink
```

Once done you can check if all works with 

```
pytest .
```

or using Makefile:

```
make test
```

Now you are ready to make your contribution


When you're done please make sure you to test your functionality 
and check the coverage of your contribution.

```
pytest --cov=ninja --cov-report term-missing tests
```

or using Makefile:

```
make test-cov
```
 
## Code style

Django Ninja uses `ruff`, and `mypy` for style checks.

Run `pre-commit install` to create a git hook to fix your styles before you commit.

Alternatively, manually check your code with:

```
ruff format --check ninja tests
ruff check ninja tests
mypy ninja
```

or using Makefile:

```
make lint
```

Or reformat your code with:

```
ruff format ninja tests
ruff check ninja tests --fix
```

or using Makefile:

```
make fmt
```
 
## Docs
Please do not forget to document your contribution

Django Ninja uses `mkdocs`:

```
cd docs/
mkdocs serve
```
and go to browser to see changes in real time



================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2025 Vitaliy Kucheryaviy

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: Makefile
================================================
.DEFAULT_GOAL := help

.PHONY: help
help:
	@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

.PHONY: install
install: ## Install dependencies
	flit install --deps develop --symlink

.PHONY: lint
lint: ## Run code linters
	ruff format --check ninja tests
	ruff check ninja tests
	mypy ninja

.PHONY: fmt format
fmt format: ## Run code formatters
	ruff format ninja tests
	ruff check --fix ninja tests

.PHONY: test
test: ## Run tests
	pytest .

.PHONY: test-cov
test-cov: ## Run tests with coverage
	pytest --cov=ninja --cov-report term-missing tests

.PHONY: docs
docs: ## Serve documentation locally
	pip install -r docs/requirements.txt
	cd docs && mkdocs serve -a localhost:8090


================================================
FILE: README.md
================================================
<a href="https://github.com/vitalik/django-ninja/issues/383"><img width="814" alt="SCR-20230123-m1t" src="https://user-images.githubusercontent.com/95222/214056666-585c0479-c122-4cb3-add4-b8844088ccdd.png"></a>



<a href="https://github.com/vitalik/django-ninja/issues/383">^ Please read ^</a>




<p align="center">
  <a href="https://django-ninja.dev/"><img src="https://django-ninja.dev/img/logo-big.png"></a>
</p>
<p align="center">
    <em>Fast to learn, fast to code, fast to run</em>
</p>


![Test](https://github.com/vitalik/django-ninja/actions/workflows/test_full.yml/badge.svg)
![Coverage](https://img.shields.io/codecov/c/github/vitalik/django-ninja)
[![PyPI version](https://badge.fury.io/py/django-ninja.svg)](https://badge.fury.io/py/django-ninja)
[![Downloads](https://static.pepy.tech/personalized-badge/django-ninja?period=month&units=international_system&left_color=black&right_color=brightgreen&left_text=downloads/month)](https://pepy.tech/project/django-ninja)

# Django Ninja - Fast Django REST Framework

**Django Ninja** is a web framework for building APIs with **Django** and Python 3.6+ **type hints**.


 **Key features:**

  - **Easy**: Designed to be easy to use and intuitive.
  - **FAST execution**: Very high performance thanks to **<a href="https://pydantic-docs.helpmanual.io" target="_blank">Pydantic</a>** and **<a href="/docs/docs/guides/async-support.md">async support</a>**.
  - **Fast to code**: Type hints and automatic docs lets you focus only on business logic.
  - **Standards-based**: Based on the open standards for APIs: **OpenAPI** (previously known as Swagger) and **JSON Schema**.
  - **Django friendly**: (obviously) has good integration with the Django core and ORM.
  - **Production ready**: Used by multiple companies on live projects (If you use django-ninja and would like to publish your feedback, please email ppr.vitaly@gmail.com).



![Django Ninja REST Framework](docs/docs/img/benchmark.png)

**Documentation**: https://django-ninja.dev

---

## Installation

```
pip install django-ninja
```



## Usage


In your django project next to urls.py create new `api.py` file:

```Python
from ninja import NinjaAPI

api = NinjaAPI()


@api.get("/add")
def add(request, a: int, b: int):
    return {"result": a + b}
```


Now go to `urls.py` and add the following:


```Python hl_lines="3 7"
...
from .api import api

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/", api.urls),  # <---------- !
]
```

**That's it !**

Now you've just created an API that:

 - receives an HTTP GET request at `/api/add`
 - takes, validates and type-casts GET parameters `a` and `b`
 - decodes the result to JSON
 - generates an OpenAPI schema for defined operation

### Interactive API docs

Now go to <a href="http://127.0.0.1:8000/api/docs" target="_blank">http://127.0.0.1:8000/api/docs</a>

You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" target="_blank">Swagger UI</a> or <a href="https://github.com/Redocly/redoc" target="_blank">Redoc</a>):

![Swagger UI](docs/docs/img/index-swagger-ui.png)


## Sponsors

<a href="https://www.sendcloud.com/"><img width="50%" alt="sendcloud-logo" src="https://github.com/user-attachments/assets/69a246d2-3dda-4473-a45c-9f0fc2f37c8c" /></a>

<a href="mailto:ppr.vitaly@gmail.com">Become a sponsor</a>



## What next?

 - Read the full documentation here - https://django-ninja.dev
 - To support this project, please give star it on Github. ![github star](docs/docs/img/github-star.png)
 - Share it [via Twitter](https://twitter.com/intent/tweet?text=Check%20out%20Django%20Ninja%20-%20Fast%20Django%20REST%20Framework%20-%20https%3A%2F%2Fdjango-ninja.dev)
 - If you already using django-ninja, please share your feedback to ppr.vitaly@gmail.com


================================================
FILE: docs/docs/chat.md
================================================
# Ask AI

Please feel free to share any questions or describe any problems you're encountering. Simply enter your text in the chat, and I'll be happy to assist you.

<style>
.serenity_chat__powered { display: none !important; }
.md-sidebar--secondary { display: none !important; }
.serenity_widget__container {
    max-width: 1200px !important;
}

.serenity_app {
    --serenity-answer-code-bg: #fafafa;
    --serenity-widget-bg: #ffffff;
}
</style>

<div id="serenity"></div>

<script>
var SERENITY_WIDGET = {
    api_url: "https://public.serenitygpt.com/api/v2/",
    api_token: "FqbM1QFShh5mGOD7",
    popup: false,
};
</script>
<script src="https://js.serenitygpt.com/widget.js"></script>


================================================
FILE: docs/docs/extra.css
================================================
.doc-module code {
  white-space: nowrap;
}

/* Ask AI Button Styles */
.ask-ai-button-container {
  display: flex;
  align-items: center;
  margin-left: auto;
  margin-right: 1rem;
}

.ask-ai-button {
  background-color: white !important;
  color: #4caf50 !important;  /* Material green-500 */
  padding: 0.4rem 0.5rem !important;
  border-radius: 0.25rem;
  font-weight: 500;
  text-decoration: none;
  font-size: 0.9rem;
  border: 2px solid #4caf50;
  transition: all 0.2s ease-in-out;
  white-space: nowrap;
  margin-left: 8px;
}

.ask-ai-button:hover {
  background-color: #4caf50 !important;
  color: white !important;
  box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}

/* Dark mode support */
[data-md-color-scheme="slate"] .ask-ai-button {
  background-color: white !important;
  color: #4caf50 !important;
}

[data-md-color-scheme="slate"] .ask-ai-button:hover {
  background-color: #4caf50 !important;
  color: white !important;
}

/* Responsive adjustments */
@media screen and (max-width: 76.1875em) {
  .ask-ai-button-container {
    margin-right: 0.5rem;
  }
  .ask-ai-button {
    padding: 0.4rem 0.8rem !important;
    font-size: 0.85rem;
  }
}

@media screen and (max-width: 60em) {
  .ask-ai-button-container {
    display: none;  /* Hide on mobile to save space */
  }
}


================================================
FILE: docs/docs/guides/api-docs.md
================================================
# API Docs

## OpenAPI docs

Once you configured your Ninja API and started runserver -  go to <a href="http://127.0.0.1:8000/api/docs" target="_blank">http://127.0.0.1:8000/api/docs</a>

You will see the automatic, interactive API documentation (provided by the <a href="https://github.com/swagger-api/swagger-ui" target="_blank">OpenAPI / Swagger UI</a>


## CDN vs staticfiles

You are not required to put django ninja to `INSTALLED_APPS`. In that case the interactive UI is hosted by CDN.

To host docs (Js/css) from your own server - just put "ninja" to INSTALLED_APPS - in that case standard django staticfiles mechanics will host it.

## Switch to Redoc


```python
from ninja import Redoc

api = NinjaAPI(docs=Redoc())

```

Then you will see the alternative automatic documentation (provided by <a href="https://github.com/Redocly/redoc" target="_blank">Redoc</a>).

## Changing docs display settings

To set some custom settings for Swagger or Redocs you can use `settings` param on the docs class

```python
from ninja import Redoc, Swagger

api = NinjaAPI(docs=Swagger(settings={"persistAuthorization": True}))
...
api = NinjaAPI(docs=Redoc(settings={"disableSearch": True}))

```

Settings reference:

 - [Swagger configuration](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)
 - [Redoc configuration](https://redocly.com/docs/api-reference-docs/configuration/functionality/)



## Hiding docs

### Hiding the interactive docs viewer

To hide only the interactive documentation UI (Swagger or Redoc) while keeping the OpenAPI schema accessible, set `docs_url` to `None`:

```python
api = NinjaAPI(docs_url=None)
```

This disables the `/docs` endpoint but the OpenAPI schema remains available at `/openapi.json`. This is useful when you want to:

- Disable the interactive UI but keep the schema for API clients or code generators
- Use external documentation tools that consume the OpenAPI spec

### Disabling the OpenAPI schema endpoint

To disable the OpenAPI schema endpoint, set `openapi_url` to `None`:

```python
api = NinjaAPI(openapi_url=None)
```

This disables the `/openapi.json` endpoint. Since the docs viewer depends on the OpenAPI schema, this also disables the docs viewer - no documentation URLs will be registered.

### Summary

| Configuration | `/openapi.json` | `/docs` | Use Case |
|---------------|-----------------|---------|----------|
| Default | Available | Available | Development |
| `docs_url=None` | Available | Hidden | Hide UI, keep schema for clients |
| `openapi_url=None` | Hidden | Hidden | Completely hide all documentation |

## Protecting docs

To protect docs with authentication (or decorate for some other use case) use `docs_decorator` argument:

```python
from django.contrib.admin.views.decorators import staff_member_required

api = NinjaAPI(docs_decorator=staff_member_required)
```

## Extending OpenAPI Spec with custom attributes

You can extend OpenAPI spec with custom attributes, for example to add `termsOfService`

```python
api = NinjaAPI(
   openapi_extra={
       "info": {
           "termsOfService": "https://example.com/terms/",
       }
   },
   title="Demo API",
   description="This is a demo API with dynamic OpenAPI info section"
)
```

## Resolving the doc's url

The url for the api's documentation view can be reversed by referencing the view's name `openapi-view`.

In Python code, for example:
```python
from django.urls import reverse

reverse('api-1.0.0:openapi-view')

>>> '/api/docs'
```

In a Django template, for example:
```Html
<a href="{% url 'api-1.0.0:openapi-view' %}">API Docs</a>

<a href="/api/docs">API Docs</a>
```

## Creating custom docs viewer

To create your own view for OpenAPI - create a class inherited from DocsBase and overwrite `render_page` method:

```python
from ninja.openapi.docs import DocsBase

class MyDocsViewer(DocsBase):
    def render_page(self, request, api):
        ... # return http response

...

api = NinjaAPI(docs=MyDocsViewer())

```

## Using a custom favicon

The django-ninja OpenAPI docs contain a default favicon, the ninja star.
To use your own, overwrite the `ninja/favicon.html` django template.

```html
<!-- templates/ninja/favicons.html -->
{% load static %}

{% block favicons %}
    <link rel="icon" type="image/png" href="{% static 'path/to/your/favicon.png' %}">
{% endblock %}
```

for more information, see the [Django documentation on overriding templates](https://docs.djangoproject.com/en/5.2/howto/overriding-templates/).


================================================
FILE: docs/docs/guides/async-support.md
================================================
## Intro

Since **version 3.1**, Django comes with **async views support**. This allows you run efficient concurrent views that are network and/or IO bound.

```
pip install Django>=3.1 django-ninja
```

Async views work more efficiently when it comes to:

- calling external APIs over the network
- executing/waiting for database queries
- reading/writing from/to disk drives

**Django Ninja** takes full advantage of async views and makes it very easy to work with them.

## Quick example

### Code

Let's take an example.  We have an API operation that does some work (currently just sleeps for provided number of seconds) and returns a word:

```python hl_lines="5"
import time

@api.get("/say-after")
def say_after(request, delay: int, word: str):
    time.sleep(delay)
    return {"saying": word}
```

To make this code asynchronous, all you have to do is add the **`async`** keyword to a function (and use async aware libraries for work processing - in our case we will replace the stdlib `sleep` with `asyncio.sleep`):

```python hl_lines="1 4 5"
import asyncio

@api.get("/say-after")
async def say_after(request, delay: int, word: str):
    await asyncio.sleep(delay)
    return {"saying": word}
```

### Run

To run this code you need an ASGI server like <a href="https://www.uvicorn.org/" target="_blank">Uvicorn</a> or <a href="https://github.com/django/daphne" target="_blank">Daphne</a>. Let's use Uvicorn for, example:

To install Uvicorn, use:

```
pip install uvicorn
```

Then start the server:

```
uvicorn your_project.asgi:application --reload
```

> <small>
> *Note: replace `your_project` with your project package name*<br>
> *`--reload` flag used to automatically reload server if you do any changes to the code (do not use on production)*
> </small>

!!! note
    You can run async views with `manage.py runserver`, but it does not work well with some libraries, so at this time (July 2020) it is recommended to use ASGI servers like Uvicorn or Daphne.

### Test

Go to your browser and open <a href="http://127.0.0.1:8000/api/say-after?delay=3&word=hello" target="_blank">http://127.0.0.1:8000/api/say-after?delay=3&word=hello</a> (**delay=3**)
After a 3-second wait you should see the "hello" message.

Now let's flood this operation with **100 parallel requests**:

```
ab -c 100 -n 100 "http://127.0.0.1:8000/api/say-after?delay=3&word=hello"
```

which will result in something like this:

```
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   1.1      1       4
Processing:  3008 3063  16.2   3069    3082
Waiting:     3008 3062  15.7   3068    3079
Total:       3008 3065  16.3   3070    3083

Percentage of the requests served within a certain time (ms)
  50%   3070
  66%   3072
  75%   3075
  80%   3076
  90%   3081
  95%   3082
  98%   3083
  99%   3083
 100%   3083 (longest request)
```

Based on the numbers, our service was able to handle each of the 100 concurrent requests with just a little overhead.

To achieve the same concurrency with WSGI and sync operations you would need to spin up about 10 workers with 10 threads each!

## Mixing sync and async operations

Keep in mind that you can use **both sync and async operations** in your project, and **Django Ninja** will route it automatically:

```python hl_lines="2 7"

@api.get("/say-sync")
def say_after_sync(request, delay: int, word: str):
    time.sleep(delay)
    return {"saying": word}

@api.get("/say-async")
async def say_after_async(request, delay: int, word: str):
    await asyncio.sleep(delay)
    return {"saying": word}
```

## Elasticsearch example

Let's take a real world use case. For this example, let's use the latest version of Elasticsearch that now comes with async support:

```
pip install elasticsearch>=7.8.0
```

And now instead of the `Elasticsearch` class, use the `AsyncElasticsearch` class and `await` the results:

```python hl_lines="2 7 11 12"
from ninja import NinjaAPI
from elasticsearch import AsyncElasticsearch


api = NinjaAPI()

es = AsyncElasticsearch()


@api.get("/search")
async def search(request, q: str):
    resp = await es.search(
        index="documents", 
        body={"query": {"query_string": {"query": q}}},
        size=20,
    )
    return resp["hits"]
```

## Using ORM

Currently, certain key parts of Django are not able to operate safely in an async environment, as they have global state that is not coroutine-aware. These parts of Django are classified as “async-unsafe”, and are protected from execution in an async environment. **The ORM** is the main example, but there are other parts that are also protected in this way.

Learn more about async safety here in the <a href="https://docs.djangoproject.com/en/stable/topics/async/#async-safety" target="_blank">official Django docs</a>.

So, if you do this:

```python hl_lines="3"
@api.get("/blog/{post_id}")
async def search(request, post_id: int):
    blog = Blog.objects.get(pk=post_id)
    ...
```

it throws an error. Until the async ORM is implemented, you can use the `sync_to_async()` adapter:

```python hl_lines="1 3 9"
from asgiref.sync import sync_to_async

@sync_to_async
def get_blog(post_id):
    return Blog.objects.get(pk=post_id)

@api.get("/blog/{post_id}")
async def search(request, post_id: int):
    blog = await get_blog(post_id)
    ...
```

or even shorter:

```python hl_lines="3"
@api.get("/blog/{post_id}")
async def search(request, post_id: int):
    blog = await sync_to_async(Blog.objects.get)(pk=post_id)
    ...
```

There is a common **GOTCHA**: Django querysets are lazily evaluated (database query happens only when you start iterating), so this will **not** work:

```python
all_blogs = await sync_to_async(Blog.objects.all)()
# it will throw an error later when you try to iterate over all_blogs
...
```

Instead, use evaluation (with `list`):

```python
all_blogs = await sync_to_async(list)(Blog.objects.all())
...
```

Since Django **version 4.1**, Django comes with asynchronous versions of ORM operations.
These eliminate the need to use `sync_to_async` in most cases.
The async operations have the same names as their sync counterparts but are prepended with *a*. So using
the example above, you can rewrite it as:

```python hl_lines="3"
@api.get("/blog/{post_id}")
async def search(request, post_id: int):
    blog = await Blog.objects.aget(pk=post_id)
    ...
```

When working with querysets, use `async for` paired with list comprehension:

```python
all_blogs = [blog async for blog in Blog.objects.all()]
...
```

Learn more about the async ORM interface in the <a href="https://docs.djangoproject.com/en/4.1/releases/4.1/#asynchronous-orm-interface" target="_blank">official Django docs</a>.


================================================
FILE: docs/docs/guides/authentication.md
================================================
# Authentication

## Intro

**Django Ninja** provides several tools to help you deal with authentication and authorization easily, rapidly, in a standard way, and without having to study and learn <a href="https://swagger.io/docs/specification/authentication/" target="_blank">all the security specifications</a>.

The core concept is that when you describe an API operation, you can define an authentication object.

```python hl_lines="2 7"
{!./src/tutorial/authentication/code001.py!}
```

In this example, the client will only be able to call the `pets` method if it uses Django session authentication (the default is cookie based), otherwise an HTTP-401 error will be returned.

If you need to authorize only a superuser, you can use `from ninja.security import django_auth_superuser` instead.

## Automatic OpenAPI schema

Here's an example where the client, in order to authenticate, needs to pass a header:

`Authorization: Bearer supersecret`

```python hl_lines="4 5 6 7 10"
{!./src/tutorial/authentication/bearer01.py!}
```

Now go to the docs at <a href="http://localhost:8000/api/docs" target="_blank">http://localhost:8000/api/docs</a>.


![Swagger UI Auth](../img/auth-swagger-ui.png)

Now, when you click the **Authorize** button, you will get a prompt to input your authentication token.

![Swagger UI Auth](../img/auth-swagger-ui-prompt.png)

When you do test calls, the Authorization header will be passed for every request.


## Global authentication

In case you need to secure **all** methods of your API, you can pass the `auth` argument to the `NinjaAPI` constructor:


```python hl_lines="11 19"
from ninja import NinjaAPI, Form
from ninja.security import HttpBearer


class GlobalAuth(HttpBearer):
    def authenticate(self, request, token):
        if token == "supersecret":
            return token


api = NinjaAPI(auth=GlobalAuth())

# @api.get(...)
# def ...

# @api.post(...)
# def ...
```

And, if you need to overrule some of those methods, you can do that on the operation level again by passing the `auth` argument. In this example, authentication will be disabled for the `/token` operation:

```python hl_lines="19"
{!./src/tutorial/authentication/global01.py!}
```

## Available auth options

### Custom function


The "`auth=`" argument accepts any Callable object. **NinjaAPI** passes authentication only if the callable object returns a value that can be **converted to boolean `True`**. This return value will be assigned to the `request.auth` attribute.

```python hl_lines="1 2 3 6"
{!./src/tutorial/authentication/code002.py!}
```


### API Key

Some API's use API keys for authorization. An API key is a token that a client provides when making API calls to identify itself. The key can be sent in the query string:
```
GET /something?api_key=abcdef12345
```

or as a request header:

```
GET /something HTTP/1.1
X-API-Key: abcdef12345
```

or as a cookie:

```
GET /something HTTP/1.1
Cookie: X-API-KEY=abcdef12345
```

**Django Ninja** comes with built-in classes to help you handle these cases.


#### in Query

```python hl_lines="1 2 5 6 7 8 9 10 11 12"
{!./src/tutorial/authentication/apikey01.py!}
```

In this example we take a token from `GET['api_key']` and find a `Client` in the database that corresponds to this key. The Client instance will be set to the `request.auth` attribute.

Note: **`param_name`** is the name of the GET parameter that will be checked for. If not set, the default of "`key`" will be used.


#### in Header

```python hl_lines="1 4"
{!./src/tutorial/authentication/apikey02.py!}
```

#### in Cookie

```python hl_lines="1 4"
{!./src/tutorial/authentication/apikey03.py!}
```

### Django Session Authentication

**Django Ninja** provides built-in session authentication classes that leverage Django's existing session framework:

#### SessionAuth

Uses Django's default session authentication - authenticates any logged-in user:

```python
from ninja.security import SessionAuth

@api.get("/protected", auth=SessionAuth())
def protected_view(request):
    return {"user": request.auth.username}
```

#### SessionAuthSuperUser

Authenticates only users with superuser privileges:

```python
from ninja.security import SessionAuthSuperUser

@api.get("/admin-only", auth=SessionAuthSuperUser())
def admin_view(request):
    return {"message": "Hello superuser!"}
```

#### SessionAuthIsStaff

Authenticates users who are either superusers or staff members:

```python
from ninja.security import SessionAuthIsStaff

@api.get("/staff-area", auth=SessionAuthIsStaff())
def staff_view(request):
    return {"message": "Hello staff member!"}
```

These authentication classes automatically use Django's `SESSION_COOKIE_NAME` setting and check the user's authentication status through the standard Django session framework.



### HTTP Bearer

```python hl_lines="1 4 5 6 7"
{!./src/tutorial/authentication/bearer01.py!}
```

### HTTP Basic Auth

```python hl_lines="1 4 5 6 7"
{!./src/tutorial/authentication/basic01.py!}
```


## Multiple authenticators

The **`auth`** argument also allows you to pass multiple authenticators:

```python hl_lines="18"
{!./src/tutorial/authentication/multiple01.py!}
```

In this case **Django Ninja** will first check the API key `GET`, and if not set or invalid will check the `header` key.
If both are invalid, it will raise an authentication error to the response.


## Router authentication

Use `auth` argument on Router to apply authenticator to all operations declared in it:

```python
api.add_router("/events/", events_router, auth=BasicAuth())
```

or using router constructor
```python
router = Router(auth=BasicAuth())
```

This overrides any API level authentication. To allow router operations to not use the API-level authentication by default, you can explicitly set the router's `auth=None`.


## Custom exceptions

Raising an exception that has an exception handler will return the response from that handler in
the same way an operation would:

```python hl_lines="1 4"
{!./src/tutorial/authentication/bearer02.py!}
```


## Async authentication

**Django Ninja** has basic support for asynchronous authentication. While the default authentication classes are not async-compatible, you can still define your custom asynchronous authentication callables and pass them in using `auth`.

```python
async def async_auth(request):
    ...


@api.get("/pets", auth=async_auth)
def pets(request):
    ...
```


See [Handling errors](errors.md) for more information.


================================================
FILE: docs/docs/guides/decorators.md
================================================
# Decorators

Django Ninja provides flexible decorator support to wrap your API operations with additional functionality like caching, logging, authentication checks, or any custom logic.

## Understanding Decorator Modes

Django Ninja supports two modes for applying decorators:


### OPERATION Mode (Default)
- Applied **after** Django Ninja's validation
- Wraps the operation function with validated data
- Has access to parsed and validated parameters
- Useful for: business logic, logging with validated data, post-validation checks

### VIEW Mode
- Applied **before** Django Ninja's validation
- Wraps the entire Django view function
- Has access to the raw Django request
- Useful for: caching, rate limiting, Django middleware-like functionality
- Similar to Django's standard view decorators


## Using `@decorate_view`

The `@decorate_view` decorator allows you to apply Django view decorators to individual endpoints.
These decorators are always executed in VIEW mode:

```python
from django.views.decorators.cache import cache_page
from ninja import NinjaAPI
from ninja.decorators import decorate_view

api = NinjaAPI()

@api.get("/cached")
@decorate_view(cache_page(60 * 15))  # Cache for 15 minutes
def cached_endpoint(request):
    return {"data": "This response is cached"}
```

You can apply multiple decorators:

```python
from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_headers

@api.get("/multi")
@decorate_view(cache_page(300), vary_on_headers("User-Agent"))
def multi_decorated(request):
    return {"data": "Multiple decorators applied"}
```

## Using `add_decorator`

The `add_decorator` method allows you to apply decorators to multiple endpoints at once.
By default, they are executed in OPERATION mode; however, you can switch them to VIEW mode.

### Router-Level Decorators

Apply decorators to all endpoints in a router:

```python
from ninja import Router

router = Router()

# Add logging to all operations in this router
def log_operation(func):
    def wrapper(request, *args, **kwargs):
        print(f"Calling {func.__name__}")
        result = func(request, *args, **kwargs)
        print(f"Result: {result}")
        return result
    return wrapper

router.add_decorator(log_operation)  # OPERATION mode by default

@router.get("/users")
def list_users(request):
    return {"users": ["Alice", "Bob"]}

@router.get("/users/{user_id}")
def get_user(request, user_id: int):
    return {"user_id": user_id}
```

### API-Level Decorators

Apply decorators to all endpoints in your entire API:

```python
from ninja import NinjaAPI

api = NinjaAPI()

# Add CORS headers to all responses (VIEW mode)
def cors_headers(func):
    def wrapper(request, *args, **kwargs):
        response = func(request, *args, **kwargs)
        response["Access-Control-Allow-Origin"] = "*"
        return response
    return wrapper

api.add_decorator(cors_headers, mode="view")

# Now all endpoints will have CORS headers
@api.get("/data")
def get_data(request):
    return {"data": "example"}
```

## Practical Examples

### Example 1: Request Timing

```python
import time
from functools import wraps

def timing_decorator(func):
    @wraps(func)
    def wrapper(request, *args, **kwargs):
        start = time.time()
        result = func(request, *args, **kwargs)
        duration = time.time() - start
        if isinstance(result, dict):
            result["_timing"] = f"{duration:.3f}s"
        return result
    return wrapper

router = Router()
router.add_decorator(timing_decorator)

@router.get("/slow")
def slow_endpoint(request):
    time.sleep(1)
    return {"message": "done"}
# Returns: {"message": "done", "_timing": "1.001s"}
```

### Example 2: Authentication Check (OPERATION mode)

```python
from functools import wraps

def require_feature_flag(flag_name):
    def decorator(func):
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            if not request.user.has_feature(flag_name):
                return {"error": f"Feature {flag_name} not enabled"}
            return func(request, *args, **kwargs)
        return wrapper
    return decorator

router = Router()
router.add_decorator(require_feature_flag("new_api"))

@router.get("/new-feature")
def new_feature(request):
    return {"feature": "enabled"}
```

### Example 3: Response Caching (VIEW mode)

```python
from django.core.cache import cache
from functools import wraps
import hashlib

def cache_response(timeout=300):
    def decorator(func):
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            # Create cache key from request
            cache_key = hashlib.md5(
                f"{request.path}{request.GET.urlencode()}".encode()
            ).hexdigest()
            
            # Try to get from cache
            cached = cache.get(cache_key)
            if cached:
                return cached
            
            # Call the view
            response = func(request, *args, **kwargs)
            
            # Cache the response
            cache.set(cache_key, response, timeout)
            return response
        return wrapper
    return decorator

router = Router()
router.add_decorator(cache_response(600), mode="view")
```

## Decorator Execution Order

When multiple decorators are applied, they execute in this order:

1. API-level decorators (outermost)
2. Parent router decorators
3. Child router decorators
4. Individual endpoint decorators (innermost)

Be aware that VIEW mode decorators are executed before OPERATION mode decorators.

```python
api = NinjaAPI()
parent_router = Router()
child_router = Router()

api.add_decorator(api_decorator)
parent_router.add_decorator(parent_decorator)
child_router.add_decorator(child_decorator)

@child_router.get("/test")
@decorate_view(endpoint_decorator)
def endpoint(request):
    return {"result": "ok"}

parent_router.add_router("/child", child_router)
api.add_router("/parent", parent_router)

# Execution order:
# 1. endpoint_decorator (view)
# 1. api_decorator (operational)
# 2. parent_decorator (operational)
# 3. child_decorator (operational)
# 5. endpoint function
```

## Async Support

Decorators work with both sync and async views. When you have mixed sync/async endpoints in the same router, you need to create universal decorators that handle both cases.

### Universal Decorators for Mixed Sync/Async Routers

When you have a router with both sync and async endpoints, use `asyncio.iscoroutinefunction()` to detect the function type:

```python
import asyncio
from functools import wraps

def universal_decorator(func):
    if asyncio.iscoroutinefunction(func):
        # Handle async functions
        @wraps(func)
        async def async_wrapper(request, *args, **kwargs):
            # Your async logic here
            result = await func(request, *args, **kwargs)
            if isinstance(result, dict):
                result["decorated"] = True
                result["type"] = "async"
            return result
        return async_wrapper
    else:
        # Handle sync functions  
        @wraps(func)
        def sync_wrapper(request, *args, **kwargs):
            # Your sync logic here
            result = func(request, *args, **kwargs)
            if isinstance(result, dict):
                result["decorated"] = True
                result["type"] = "sync"
            return result
        return sync_wrapper

router = Router()
router.add_decorator(universal_decorator)

@router.get("/async")
async def async_endpoint(request):
    await asyncio.sleep(0.1)
    return {"endpoint": "async"}

@router.get("/sync") 
def sync_endpoint(request):
    return {"endpoint": "sync"}
```

### Async-Only Decorators

For routers with only async endpoints, you can use async decorators directly:

```python
def async_timing_decorator(func):
    @wraps(func)
    async def wrapper(request, *args, **kwargs):
        start = time.time()
        result = await func(request, *args, **kwargs)
        duration = time.time() - start
        if isinstance(result, dict):
            result["_timing"] = f"{duration:.3f}s"
        return result
    return wrapper

router = Router()
router.add_decorator(async_timing_decorator)

@router.get("/async")
async def async_endpoint(request):
    await asyncio.sleep(1)
    return {"message": "async done"}
```

### Sync Decorators on Async Views

You can also use sync decorators on async views by handling coroutines:

```python
def sync_decorator(func):
    @wraps(func)
    def wrapper(request, *args, **kwargs):
        result = func(request, *args, **kwargs)
        
        if asyncio.iscoroutine(result):
            # Handle async functions
            async def async_wrapper():
                actual_result = await result
                if isinstance(actual_result, dict):
                    actual_result["sync_decorated"] = True
                return actual_result
            return async_wrapper()
        else:
            # Handle sync functions
            if isinstance(result, dict):
                result["sync_decorated"] = True
            return result
    return wrapper
```

## When to Use Each Mode

### Use VIEW Mode When:
- You need access to the raw Django request
- Implementing caching at the HTTP level
- Adding/modifying HTTP headers
- Implementing rate limiting
- Working with Django middleware patterns

### Use OPERATION Mode When:
- You need access to validated/parsed data
- Implementing business logic decorators
- Adding data to responses
- Logging with type-safe parameters
- Post-validation security checks

## Best Practices

1. **Use `functools.wraps`**: Always use `@wraps(func)` to preserve function metadata

2. **Handle mixed sync/async routers**: When your router has both sync and async endpoints, use `asyncio.iscoroutinefunction(func)` to create universal decorators

3. **Choose the right approach for async**:
   - **Universal decorators**: Best for mixed routers (detect with `iscoroutinefunction`)
   - **Async-only decorators**: Best for async-only routers (simpler, cleaner) 
   - **Sync decorators with coroutine handling**: Useful for legacy decorators

4. **Be mindful of performance**: Decorators add overhead, especially in VIEW mode

5. **Document side effects**: Clearly document what your decorators modify

6. **Keep decorators focused**: Each decorator should have a single responsibility

7. **Test both sync and async**: When using universal decorators, test both sync and async endpoints


================================================
FILE: docs/docs/guides/errors.md
================================================
# Handling errors

**Django Ninja** allows you to install custom exception handlers to deal with how you return responses when errors or handled exceptions occur.

## Custom exception handlers

Let's say you are making API that depends on some external service that is designed to be unavailable at some moments. Instead of throwing default 500 error upon exception - you can handle the error and give some friendly response back to the client (to come back later)

To achieve that you need:

1. create some exception (or use existing one)
2. use api.exception_handler decorator


Example:


```python hl_lines="9 10"
api = NinjaAPI()

class ServiceUnavailableError(Exception):
    pass


# initializing handler

@api.exception_handler(ServiceUnavailableError)
def service_unavailable(request, exc):
    return api.create_response(
        request,
        {"message": "Please retry later"},
        status=503,
    )


# some logic that throws exception

@api.get("/service")
def some_operation(request):
    if random.choice([True, False]):
        raise ServiceUnavailableError()
    return {"message": "Hello"}

```

Exception handler function takes 2 arguments:

 - **request** - Django http request
 - **exc** - actual exception

function must return http response

## Override the default exception handlers

**Django Ninja** registers default exception handlers for the types shown below.
You can register your own handlers with `@api.exception_handler` to override the default handlers.

#### `ninja.errors.AuthenticationError`

Raised when authentication data is not valid

#### `ninja.errors.AuthorizationError`

Raised when authentication data is valid, but doesn't allow you to access the resource

#### `ninja.errors.ValidationError`

Raised when request data does not validate

#### `ninja.errors.HttpError`

Used to throw http error with status code from any place of the code

#### `django.http.Http404`
 
 Django's default 404 exception (can be returned f.e. with `get_object_or_404`)

#### `Exception`
 
Any other unhandled exception by application.

Default behavior 
 
  - **if `settings.DEBUG` is `True`** - returns a traceback in plain text (useful when debugging in console or swagger UI)
  - **else** - default django exception handler mechanism is used (error logging, email to ADMINS)


## Customizing request validation errors

Requests that fail validation raise `ninja.errors.ValidationError` (not to be confused with `pydantic.ValidationError`).
`ValidationError`s have a default exception handler that returns a 422 (Unprocessable Content) JSON response of the form:
```json
{
    "detail": [ ... ]
}
```

You can change this behavior by overriding the default handler for `ValidationError`s:

```python hl_lines="1 4"
from ninja.errors import ValidationError
...

@api.exception_handler(ValidationError)
def validation_errors(request, exc):
    return HttpResponse("Invalid input", status=422)
```

If you need even more control over validation errors (for example, if you need to reference the schema associated with
the model that failed validation), you can supply your own `validation_error_from_error_contexts` in a `NinjaAPI` subclass:

```python hl_lines="4"
from ninja.errors import ValidationError, ValidationErrorContext
from typing import Any, Dict, List

class CustomNinjaAPI(NinjaAPI):
    def validation_error_from_error_contexts(
        self, error_contexts: List[ValidationErrorContext],
    ) -> ValidationError:
        custom_error_infos: List[Dict[str, Any]] = []
        for context in error_contexts:
            model = context.model
            pydantic_schema = model.__pydantic_core_schema__
            param_source = model.__ninja_param_source__
            for e in context.pydantic_validation_error.errors(
                include_url=False, include_context=False, include_input=False
            ):
                custom_error_info = {
                # TODO: use `e`, `param_source`, and `pydantic_schema` as desired
                }
                custom_error_infos.append(custom_error_info)
        return ValidationError(custom_error_infos)

api = CustomNinjaAPI()
```

Now each `ValidationError` raised during request validation will contain data from your `validation_error_from_error_contexts`.


## Throwing HTTP responses with exceptions

As an alternative to custom exceptions and writing handlers for it - you can as well throw http exception that will lead to returning a http response with desired code


```python
from ninja.errors import HttpError

@api.get("/some/resource")
def some_operation(request):
    if True:
        raise HttpError(503, "Service Unavailable. Please retry later.")

```


================================================
FILE: docs/docs/guides/input/body.md
================================================
# Request Body

Request bodies are typically used with “create” and “update” operations (POST, PUT, PATCH).
For example, when creating a resource using POST or PUT, the request body usually contains the representation of the resource to be created.

To declare a **request body**, you need to use **Django Ninja `Schema`**.

!!! info
    Under the hood **Django Ninja** uses <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> models with all their power and benefits.
    The alias `Schema` was chosen to avoid confusion in code when using Django models, as Pydantic's model class is called Model by default, and conflicts with Django's Model class.

## Import Schema

First, you need to import `Schema` from `ninja`:

```python hl_lines="2"
{!./src/tutorial/body/code01.py!}
```

## Create your data model

Then you declare your data model as a class that inherits from `Schema`.

Use standard Python types for all the attributes:

```python hl_lines="5 6 7 8 9"
{!./src/tutorial/body/code01.py!}
```

Note: if you use **`None`** as the default value for an attribute, it will become optional in the request body.
For example, this model above declares a JSON "`object`" (or Python `dict`) like:

```JSON
{
    "name": "Katana",
    "description": "An optional description",
    "price": 299.00,
    "quantity": 10
}
```

...as `description` is optional (with a default value of `None`), this JSON "`object`" would also be valid:

```JSON
{
    "name": "Katana",
    "price": 299.00,
    "quantity": 10
}
```

## Declare it as a parameter

To add it to your *path operation*, declare it the same way you declared the path and query parameters:

```python hl_lines="13"
{!./src/tutorial/body/code01.py!}
```

... and declare its type as the model you created, `Item`.

## Results

With just that Python type declaration, **Django Ninja** will:

* Read the body of the request as JSON.
* Convert the corresponding types (if needed).
* Validate the data.
    * If the data is invalid, it will return a nice and meaningful error, indicating exactly where and what the incorrect data was.
* Give you the received data in the parameter `item`.
    * Because you declared it in the function to be of type `Item`, you will also have all the editor support
      (completion, etc.) for all the attributes and their types.
* Generate <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> definitions for
  your models, and you can also use them anywhere else you like if it makes sense for your project.
* Those schemas will be part of the generated OpenAPI schema, and used by the automatic documentation <abbr title="User Interfaces">UI's</abbr>.

## Automatic docs

The JSON Schemas of your models will be part of your OpenAPI generated schema, and will be shown in the interactive API docs:

![Openapi schema](../../img/body-schema-doc.png)

... and they will be also used in the API docs inside each *path operation* that needs them:

![Openapi schema](../../img/body-schema-doc2.png)

## Editor support

In your editor, inside your function you will get type hints and completion everywhere (this wouldn't happen if you received a `dict` instead of a Schema object):

![Type hints](../../img/body-editor.gif)


The previous screenshots were taken with <a href="https://code.visualstudio.com" class="external-link" target="_blank">Visual Studio Code</a>.

You would get the same editor support with <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> and most of the other Python editors.


## Request body + path parameters

You can declare path parameters **and** body requests at the same time.

**Django Ninja** will recognize that the function parameters that match path parameters should be **taken from the path**, and that function parameters that are declared with `Schema` should be **taken from the request body**.

```python hl_lines="11 12"
{!./src/tutorial/body/code02.py!}
```

## Request body + path + query parameters

You can also declare **body**, **path** and **query** parameters, all at the same time.

**Django Ninja** will recognize each of them and take the data from the correct place.

```python hl_lines="11 12"
{!./src/tutorial/body/code03.py!}
```

The function parameters will be recognized as follows:

* If the parameter is also declared in the **path**, it will be used as a path parameter.
* If the parameter is of a **singular type** (like `int`, `float`, `str`, `bool`, etc.), it will be interpreted as a **query** parameter.
* If the parameter is declared to be of the type of **Schema** (or Pydantic `BaseModel`), it will be interpreted as a request **body**.


================================================
FILE: docs/docs/guides/input/file-params.md
================================================
# File uploads

Handling files are no different from other parameters.

```python hl_lines="1 2 5"
from ninja import NinjaAPI, File
from ninja.files import UploadedFile

@api.post("/upload")
def upload(request, file: File[UploadedFile]):
    data = file.read()
    return {'name': file.name, 'len': len(data)}
```


`UploadedFile` is an alias to [Django's UploadFile](https://docs.djangoproject.com/en/stable/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile) and has all the methods and attributes to access the uploaded file:

 - read()
 - multiple_chunks(chunk_size=None)
 - chunks(chunk_size=None)
 - name
 - size
 - content_type
 - content_type_extra
 - charset
 - etc.

## Uploading array of files

To **upload several files** at the same time, just declare a `List` of `UploadedFile`:


```python hl_lines="1 6"
from typing import List
from ninja import NinjaAPI, File
from ninja.files import UploadedFile

@api.post("/upload-many")
def upload_many(request, files: File[List[UploadedFile]]):
    return [f.name for f in files]
```

## Uploading files with extra fields

Note: The HTTP protocol does not allow you to send files in `application/json` format by default (unless you encode it somehow to JSON on client side)

To send files along with some extra attributes, you need to send bodies with `multipart/form-data` encoding. You can do it by simply marking fields with `Form`:

```python hl_lines="14"
from ninja import NinjaAPI, Schema, UploadedFile, Form, File
from datetime import date

api = NinjaAPI()


class UserDetails(Schema):
    first_name: str
    last_name: str
    birthdate: date


@api.post('/users')
def create_user(request, details: Form[UserDetails], file: File[UploadedFile]):
    return [details.dict(), file.name]

```

Note: in this case all fields should be send as form fields

You can as well send payload in single field as JSON - just remove the Form mark from:

```python
@api.post('/users')
def create_user(request, details: UserDetails, file: File[UploadedFile]):
    return [details.dict(), file.name]

```

this will expect from the client side to send data as `multipart/form-data with 2 fields:
  
  - details: JSON as string
  - file: file


### List of files with extra info

```python
@api.post('/users')
def create_user(request, details: Form[UserDetails], files: File[list[UploadedFile]]):
    return [details.dict(), [f.name for f in files]]
```

### Optional file input

If you would like the file input to be optional, all that you have to do is to pass `None` to the `File` type, like so:

```python
@api.post('/users')
def create_user(request, details: Form[UserDetails], avatar: File[UploadedFile] = None):
    user = add_user_to_database(details)
    if avatar is not None:
        set_user_avatar(user)
```


## Handling request.FILES in PUT/PATCH Requests

**Problem**

```python
@api.put("/upload") # !!!!
def upload(request, file: File[UploadedFile]):
   ...
```

For some [historical reasons Django’s](https://groups.google.com/g/django-users/c/BeBKj_6qNsc) `request.FILES` is populated only for POST requests by default. When using HTTP PUT or PATCH methods with file uploads (e.g., multipart/form-data), request.FILES will not contain uploaded files. This is a known Django behavior, not specific to Django Ninja.

As a result, views expecting files in PUT or PATCH requests may not behave correctly, since request.FILES will be empty.

**Solution**

Django Ninja provides a built-in middleware to automatically fix this behavior:
`ninja.compatibility.files.fix_request_files_middleware`

This middleware will manually parse multipart/form-data for PUT and PATCH requests and populate request.FILES, making file uploads work as expected across all HTTP methods.

**Usage**

To enable the middleware, add the following to your Django settings:

```python
MIDDLEWARE = [
    # ... your existing middleware ...
    "ninja.compatibility.files.fix_request_files_middleware",
]
```

**Auto-detection**

When Django Ninja detects a PUT or PATCH  etc methods with multipart/form-data and expected FILES  - it will throw an error message suggesting you install the compatibility middleware:


Note: This middleware does not interfere with normal POST behavior or any other methods.




================================================
FILE: docs/docs/guides/input/filtering.md
================================================
# Filtering

If you want to allow the user to filter your querysets by a number of different attributes, it makes sense
to encapsulate your filters into a `FilterSchema` class. `FilterSchema` is a regular `Schema`, so it's using all the
necessary features of Pydantic, but it also adds some bells and whistles that ease the translation of the user-facing filtering
parameters into database queries. 

Start off with defining a subclass of `FilterSchema`:

```python hl_lines="6 7 8 9"
from ninja import FilterSchema
from typing import Optional
from datetime import datetime


class BookFilterSchema(FilterSchema):
    name: Optional[str] = None
    author: Optional[str] = None
    created_after: Optional[datetime] = None
```


Next, use this schema in conjunction with `Query` in your API handler:
```python hl_lines="2"
@api.get("/books")
def list_books(request, filters: BookFilterSchema = Query(...)):
    books = Book.objects.all()
    books = filters.filter(books)
    return books
```

Just like described in [defining query params using schema](./query-params.md#using-schema), Django Ninja converts the fields
defined in `BookFilterSchema` into query parameters.

You can use a shorthand one-liner `.filter()` to apply those filters to your queryset:
```python hl_lines="4"
@api.get("/books")
def list_books(request, filters: Query[BookFilterSchema]):
    books = Book.objects.all()
    books = filters.filter(books)
    return books
```

Under the hood, `FilterSchema` converts its fields into [Q expressions](https://docs.djangoproject.com/en/3.1/topics/db/queries/#complex-lookups-with-q-objects) which it then combines and uses to filter your queryset.


Alternatively to using the `.filter` method, you can get the prepared `Q`-expression and perform the filtering yourself.
That can be useful, when you have some additional queryset filtering on top of what you expose to the user through the API:
```python hl_lines="5 8"
@api.get("/books")
def list_books(request, filters: Query[BookFilterSchema]):

    # Never serve books from inactive publishers and authors
    q = Q(author__is_active=True) | Q(publisher__is_active=True)
    
    # But allow filtering the rest of the books
    q &= filters.get_filter_expression()
    return Book.objects.filter(q)
```

By default, the filters will behave the following way:

* `None` values will be ignored and not filtered against;
* Every non-`None` field will be converted into a `Q`-expression based on the `Field` definition of each field;
* All `Q`-expressions will be merged into one using `AND` logical operator;
* The resulting `Q`-expression is used to filter the queryset and return you a queryset with a `.filter` clause applied.

## Customizing Fields
By default, `FilterSet` will use the field names to generate Q expressions:
```python
class BookFilterSchema(FilterSchema):
    name: Optional[str] = None
```
The `name` field will be converted into `Q(name=...)` expression.

When your database lookups are more complicated than that, you can annotate your fields with an instance of `FilterLookup` where you specify how you wish your field to be looked up for filtering:
```python hl_lines="5"
from ninja import FilterSchema, FilterLookup
from typing import Annotated

class BookFilterSchema(FilterSchema):
    name: Annotated[Optional[str], FilterLookup("name__icontains")] = None
```

You can even specify multiple lookups as a list:
```python hl_lines="3 4 5"
class BookFilterSchema(FilterSchema):
    search: Annotated[Optional[str], FilterLookup(
        ["name__icontains",
         "author__name__icontains",
         "publisher__name__icontains"]
    )]
```

By default, field-level expressions are combined using `"OR"` connector, so with the above setup, a query parameter `?search=foobar` will search for books that have "foobar" in either of their name, author or publisher.

And to make generic fields, you can make the field name implicit by skipping it:
```python hl_lines="1 4"
IContainsField = Annotated[Optional[str], FilterLookup('__icontains')]

class BookFilterSchema(FilterSchema):
    name: IContainsField = None
```

??? note "Deprecated syntax"

    In previous versions, database lookups were specified using `Field(q=...)` syntax:
    ```python
    from ninja import FilterSchema, Field
    
    class BookFilterSchema(FilterSchema):
        name: Optional[str] = Field(None, q="name__icontains")
    ```
    
    This approach is still supported, but it is considered **deprecated** and **not recommended** for new code because:
    
    - Poor IDE support (IDEs don't recognize custom `Field` arguments)
    - Uses deprecated Pydantic features (`**extra`)
    - Less type-safe and harder to maintain
    
    The new `FilterLookup` annotation provides better developer experience with full IDE support and type safety. Prefer using `FilterLookup` for new projects.


## Combining expressions
By default,

* Field-level expressions are joined together using `OR` operator.
* The fields themselves are joined together using `AND` operator.

So, with the following `FilterSchema`...
```python
class BookFilterSchema(FilterSchema):
    search: Annotated[
        Optional[str],
        FilterLookup(["name__icontains", "author__name__icontains"])] = None
    popular: Optional[bool] = None
```
...and the following query parameters from the user
```
http://localhost:8000/api/books?search=harry&popular=true
```
the `FilterSchema` instance will look for popular books that have `harry` in the book's _or_ author's name. 


You can customize this behavior using an `expression_connector` argument in field-level and class-level definition:
```python hl_lines="12"
from ninja import FilterConfigDict, FilterLookup, FilterSchema

class BookFilterSchema(FilterSchema):
    active: Annotated[
        Optional[bool],
        FilterLookup(
            ["is_active", "publisher__is_active"],
            expression_connector="AND"
        )] = None
    name: Annotated[Optional[str], FilterLookup("name__icontains")] = None
    
    model_config = FilterConfigDict(expression_connector="OR")
```

An expression connector can take the values of `"OR"`, `"AND"` and `"XOR"`, but the latter is only [supported](https://docs.djangoproject.com/en/4.1/ref/models/querysets/#xor) in Django starting with 4.1.

Now, a request with these query parameters 
```
http://localhost:8000/api/books?name=harry&active=true
```
...shall search for books that have `harry` in their name _or_ are active themselves _and_ are published by active publishers.


## Filtering by Nones
You can make the `FilterSchema` treat `None` as a valid value that should be filtered against.

This can be done on a field level with a `ignore_none` kwarg:
```python hl_lines="3"
class BookFilterSchema(FilterSchema):
    name: Annotated[Optional[str], FilterLookup("name__icontains")] = None
    tag: Annotated[Optional[str], FilterLookup("tag", ignore_none=False)] = None
```

This way when no other value for `"tag"` is provided by the user, the filtering will always include a condition `tag=None`.

You can also specify this setting for all fields at the same time in `model_config`:
```python hl_lines="5"
class BookFilterSchema(FilterSchema):
    name: Annotated[Optional[str], FilterLookup("name__icontains")] = None
    tag: Optional[str] = None
    
    model_config = FilterConfigDict(ignore_none=False)
```


## Custom expressions
Sometimes you might want to have complex filtering scenarios that cannot be handled by individual Field annotations.
For such cases you can implement your field filtering logic as a custom method. Simply define a method called `filter_<fieldname>` which takes a filter value and returns a Q expression:

```python hl_lines="5"
class BookFilterSchema(FilterSchema):
    tag: Optional[str] = None
    popular: Optional[bool] = None
    
    def filter_popular(self, value: bool) -> Q:
        return Q(view_count__gt=1000) | Q(download_count__gt=100) if value else Q()
```
Such field methods take precedence over what is specified in the `Field()` definition of the corresponding fields.

If that is not enough, you can implement your own custom filtering logic for the entire `FilterSet` class in a `custom_expression` method:

```python hl_lines="5"
class BookFilterSchema(FilterSchema):
    name: Optional[str] = None
    popular: Optional[bool] = None

    def custom_expression(self) -> Q:
        q = Q()
        if self.name:
            q &= Q(name__icontains=self.name)
        if self.popular:
            q &= (
                Q(view_count__gt=1000) |
                Q(downloads__gt=100) |
                Q(tag='popular')
            )
        return q
```
The `custom_expression` method takes precedence over any other definitions described earlier, including `filter_<fieldname>` methods.


================================================
FILE: docs/docs/guides/input/form-params.md
================================================
# Form data

**Django Ninja** also allows you to parse and validate `request.POST` data
(aka `application/x-www-form-urlencoded` or `multipart/form-data`).

## Form Data as params 

```python hl_lines="1 4"
from ninja import NinjaAPI, Form

@api.post("/login")
def login(request, username: Form[str], password: Form[str]):
    return {'username': username, 'password': '*****'}
```

Note the following:

1) You need to import the `Form` class from `ninja`
```python
from ninja import Form
```

2) Use `Form` as default value for your parameter:
```python
username: Form[str]
```

## Using a Schema

In a similar manner to [Body](body.md#declare-it-as-a-parameter), you can use
a Schema to organize your parameters.

```python hl_lines="12"
{!./src/tutorial/form/code01.py!}
```

## Request form + path + query parameters

In a similar manner to [Body](body.md#request-body-path-query-parameters), you can use
Form data in combination with other parameter sources.

You can declare query **and** path **and** form field, **and** etc... parameters at the same time.

**Django Ninja** will recognize that the function parameters that match path
parameters should be **taken from the path**, and that function parameters that
are declared with `Form(...)` should be **taken from the request form fields**, etc.

```python hl_lines="12"
{!./src/tutorial/form/code02.py!}
```
## Mapping Empty Form Field to Default

Form fields that are optional, are often sent with an empty value. This value is
interpreted as an empty string, and thus may fail validation for fields such as `int` or `bool`.

This can be fixed, as described in the Pydantic docs, by using
[Generic Classes as Types](https://pydantic-docs.helpmanual.io/usage/types/#generic-classes-as-types).

```python hl_lines="15 16 23-25"
{!./src/tutorial/form/code03.py!}
```


================================================
FILE: docs/docs/guides/input/operations.md
================================================
# HTTP Methods

## Defining operations

An `operation` can be one of the following [HTTP methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods):

- GET
- POST
- PUT
- DELETE
- PATCH

**Django Ninja** comes with a decorator for each operation:

```python hl_lines="1 5 9 13 17"
@api.get("/path")
def get_operation(request):
    ...

@api.post("/path")
def post_operation(request):
    ...

@api.put("/path")
def put_operation(request):
    ...

@api.delete("/path")
def delete_operation(request):
    ...

@api.patch("/path")
def patch_operation(request):
    ...
```

See the [operations parameters](../../reference/operations-parameters.md)
reference docs for information on what you can pass to any of these decorators.

## Handling multiple methods

If you need to handle multiple methods with a single function for a given path,
you can use the `api_operation` decorator:

```python hl_lines="1"
@api.api_operation(["POST", "PATCH"], "/path")
def mixed_operation(request):
    ...
```

This feature can also be used to implement other HTTP methods that don't have
corresponding **Django Ninja** methods, such as `HEAD` or `OPTIONS`.

```python hl_lines="1"
@api.api_operation(["HEAD", "OPTIONS"], "/path")
def mixed_operation(request):
    ...
```


================================================
FILE: docs/docs/guides/input/path-params.md
================================================
# Path parameters
You can declare path "parameters" with the same syntax used by Python format-strings (which luckily also matches the <a href="https://swagger.io/docs/specification/describing-parameters/#path-parameters" target="_blank">OpenAPI path parameters</a>):

```python hl_lines="1 2"
{!./src/tutorial/path/code01.py!}
```

The value of the path parameter `item_id` will be passed to your function as the argument `item_id`.

So, if you run this example and go to <a href="http://localhost:8000/api/items/foo" target="_blank">http://localhost:8000/api/items/foo</a>, you will see this response:

```JSON
{"item_id":"foo"}
```


### Path parameters with types
You can declare the type of path parameter in the function using standard Python type annotations:

```python hl_lines="2"
{!./src/tutorial/path/code02.py!}
```

In this case,`item_id` is declared to be an **`int`**. This will give you editor and linter support for error checks, completion, etc.

If you run this in your browser with <a href="http://localhost:8000/api/items/3" target="_blank">http://localhost:8000/api/items/3</a>, you will see this response:
```JSON
{"item_id":3}
```

!!! tip
    Notice that the value your function received (and returned) is **3**, as a Python `int` - not a string `"3"`.
    So, with just that type declaration, **Django Ninja** gives you automatic request "parsing" and validation.



### Data validation
On the other hand, if you go to the browser at <a href="http://localhost:8000/api/items/foo" target="_blank">http://localhost:8000/api/items/foo</a> <small>*(`"foo"` is not int)*</small>, you will see an HTTP error like this:

```JSON hl_lines="8"
{
    "detail": [
        {
            "loc": [
                "path",
                "item_id"
            ],
            "msg": "value is not a valid integer",
            "type": "type_error.integer"
        }
    ]
}
```


### Django Path Converters

You can use [Django Path Converters](https://docs.djangoproject.com/en/stable/topics/http/urls/#path-converters)
to help parse the path:

```python hl_lines="1"
@api.get("/items/{int:item_id}")
def read_item(request, item_id):
    return {"item_id": item_id}
```

In this case,`item_id` will be parsed as an **`int`**. If `item_id` is not a valid `int`, the url will not
match.  (e.g. if no other path matches, a *404 Not Found* will be returned)

!!! tip
    Notice that, since **Django Ninja** uses a default type of `str` for unannotated parameters, the value the
    function above received (and returned) is `"3"`, as a Python `str` - not an integer **3**. To receive
    an `int`, simply declare `item_id` as an `int` type annotation in the function definition as normal:

    ```python hl_lines="2"
    @api.get("/items/{int:item_id}")
    def read_item(request, item_id:int):
        return {"item_id": item_id}
    ```
 
#### Path params with slashes

Django's `path` converter allows you to handle path-like parameters:

```python hl_lines="1"
@api.get('/dir/{path:value}')
def someview(request, value: str):
    return value
```
you can query this operation with `/dir/some/path/with-slashes` and your `value` will be equal to `some/path/with-slashes`

### Multiple parameters

You can pass as many variables as you want into `path`, just remember to have unique names and don't forget to use the same names in the function arguments.

```python
@api.get("/events/{year}/{month}/{day}")
def events(request, year: int, month: int, day: int):
    return {"date": [year, month, day]}
```


### Using Schema

You can also use Schema to encapsulate path parameters that depend on each other (and validate them as a group):


```python hl_lines="1 2  5 6 7 8 9 10 11 15"
{!./src/tutorial/path/code010.py!}
```

!!! note
    Notice that here we used a `Path` source hint to let **Django Ninja** know that this schema will be applied to path parameters.

### Documentation
Now, when you open your browser at <a href="http://localhost:8000/api/docs" target="_blank">http://localhost:8000/api/docs</a>, you will see the automatic, interactive, API documentation.
![Django Ninja Swagger](../../img/tutorial-path-swagger.png)


================================================
FILE: docs/docs/guides/input/query-params.md
================================================
# Query parameters

When you declare other function parameters that are not part of the path parameters, they are automatically interpreted as "query" parameters.

```python hl_lines="5"
{!./src/tutorial/query/code01.py!}
```

To query this operation, you use a URL like:

```
http://localhost:8000/api/weapons?offset=0&limit=10
```
By default, all GET parameters are strings, and when you annotate your function arguments with types, they are converted to that type and validated against it.

The same benefits that apply to path parameters also apply to query parameters:

- Editor support (obviously)
- Data "parsing"
- Data validation
- Automatic documentation


!!! Note
    if you do not annotate your arguments, they will be treated as `str` types

```python hl_lines="2"
@api.get("/weapons")
def list_weapons(request, limit, offset):
    # type(limit) == str
    # type(offset) == str
```

### Defaults

As query parameters are not a fixed part of a path, they are optional and can have default values:

```python hl_lines="2"
@api.get("/weapons")
def list_weapons(request, limit: int = 10, offset: int = 0):
    return weapons[offset : offset + limit]
```

In the example above we set default values of `offset=0` and `limit=10`.

So, going to the URL:
```
http://localhost:8000/api/weapons
```
would be the same as going to:
```
http://localhost:8000/api/weapons?offset=0&limit=10
```
If you go to, for example:
```
http://localhost:8000/api/weapons?offset=20
```

the parameter values in your function will be:

 - `offset=20`  (because you set it in the URL)
 - `limit=10`  (because that was the default value)


### Required and optional parameters

You can declare required or optional GET parameters in the same way as declaring Python function arguments:

```python hl_lines="5"
{!./src/tutorial/query/code02.py!}
```

In this case, **Django Ninja** will always validate that you pass the `q` param in the GET, and the `offset` param is an optional integer.

### GET parameters type conversion

Let's declare multiple type arguments:
```python hl_lines="5"
{!./src/tutorial/query/code03.py!}
```
The `str` type is passed as is.

For the `bool` type, all the following:
```
http://localhost:8000/api/example?b=1
http://localhost:8000/api/example?b=True
http://localhost:8000/api/example?b=true
http://localhost:8000/api/example?b=on
http://localhost:8000/api/example?b=yes
```
or any other case variation (uppercase, first letter in uppercase, etc.), your function will see
the parameter `b` with a `bool` value of `True`, otherwise as `False`.

Date can be both date string and integer (unix timestamp):

<pre style="font-size: .85em; background-color:rgb(245, 245, 245);">
http://localhost:8000/api/example?d=<strong>1577836800</strong>  # same as 2020-01-01
http://localhost:8000/api/example?d=<strong>2020-01-01</strong>
</pre>


### Using Schema

You can also use Schema to encapsulate GET parameters:

```python hl_lines="1 2  5 6 7 8"
{!./src/tutorial/query/code010.py!}
```

For more complex filtering scenarios please refer to [filtering](./filtering.md).


================================================
FILE: docs/docs/guides/input/request-parsers.md
================================================
# Request parsers

In most cases, the default content type for REST API's is JSON, but in case you need to work with
other content types (like YAML, XML, CSV) or use faster JSON parsers, **Django Ninja** provides a `parser` configuration.

```python
api = NinjaAPI(parser=MyYamlParser())
```

To create your own parser, you need to extend the `ninja.parser.Parser` class, and override the `parse_body` method.


## Example YAML Parser

Let's create our custom YAML parser:

```python hl_lines="4 8 9"
import yaml
from typing import List
from ninja import NinjaAPI
from ninja.parser import Parser


class MyYamlParser(Parser):
    def parse_body(self, request):
        return yaml.safe_load(request.body)


api = NinjaAPI(parser=MyYamlParser())


class Payload(Schema):
    ints: List[int]
    string: str
    f: float


@api.post('/yaml')
def operation(request, payload: Payload):
    return payload.dict()


```

If you now send YAML like this as the request body:

```YAML
ints:
 - 0
 - 1
string: hello
f: 3.14
```

it will be correctly parsed, and you should have JSON output like this:


```JSON
{
  "ints": [
    0,
    1
  ],
  "string": "hello",
  "f": 3.14
}
```


## Example ORJSON Parser

[orjson](https://github.com/ijl/orjson#orjson) is a fast, accurate JSON library for Python. It benchmarks as the fastest Python library for JSON and is more accurate than the standard `json` library or other third-party libraries.

```
pip install orjson
```

Parser code:

```python hl_lines="1 8 9"
import orjson
from ninja import NinjaAPI
from ninja.parser import Parser


class ORJSONParser(Parser):
    def parse_body(self, request):
        return orjson.loads(request.body)


api = NinjaAPI(parser=ORJSONParser())
```



================================================
FILE: docs/docs/guides/response/config-pydantic.md
================================================
# Overriding Pydantic Config

There are many customizations available for a **Django Ninja `Schema`**, via the schema's
[Pydantic `model_config`](https://docs.pydantic.dev/latest/api/config/). 

!!! info
    Under the hood **Django Ninja** uses [Pydantic Models](https://pydantic-docs.helpmanual.io/usage/models/)
    with all their power and benefits. The alias `Schema` was chosen to avoid confusion in code
    when using Django models, as Pydantic's model class is called Model by default, and conflicts with
    Django's Model class.

## Example Camel Case mode

One interesting config attribute is [`alias_generator`](https://docs.pydantic.dev/latest/api/config/?query=alias_generator#pydantic.config.ConfigDict.alias_generator).
Using Pydantic's example in **Django Ninja** can look something like:

```python hl_lines="10"
from pydantic import ConfigDict
from ninja import Schema


def to_camel(string: str) -> str:
    words = string.split('_')
    return words[0].lower() + ''.join(word.capitalize() for word in words[1:])

class CamelModelSchema(Schema):
    model_config = ConfigDict(alias_generator=to_camel)
    str_field_name: str
    float_field_name: float
```

Keep in mind that when you want modify output for field names (like camel case) - you need to set as well  `populate_by_name` and `by_alias`

```python hl_lines="6 14"
from pydantic import ConfigDict

class UserSchema(ModelSchema):
    model_config = ConfigDict(
        alias_generator = to_camel
        populate_by_name = True,  # !!!!!! <--------
    )
    class Meta:
        model = User
        fields = ["id", "email", "is_staff"]



@api.get("/users", response=list[UserSchema], by_alias=True) # !!!!!! <-------- by_alias
def get_users(request):
    return User.objects.all()

```

results:

```JSON
[
  {
    "id": 1,
    "email": "tim@apple.com",
    "isStaff": true
  },
  {
    "id": 2,
    "email": "sarah@smith.com",
    "isStaff": false
  }
  ...
]

```




================================================
FILE: docs/docs/guides/response/django-pydantic-create-schema.md
================================================
# Using create_schema

Under the hood, [`ModelSchema`](django-pydantic.md#modelschema) uses the `create_schema` function.
This is a more advanced (and less safe) method - please use it carefully.

## `create_schema`

**Django Ninja** comes with a helper function `create_schema`:

```python
def create_schema(
    model, # django model
    name = "", # name for the generated class, if empty model names is used
    depth = 0, # if > 0 schema will also be created for the nested ForeignKeys and Many2Many (with the provided depth of lookup)
    fields: list[str] = None, # if passed - ONLY these fields will added to schema
    exclude: list[str] = None, # if passed - these fields will be excluded from schema
    optional_fields: list[str] | str = None, # if passed - these fields will not be required on schema (use '__all__' to mark ALL fields required)
    custom_fields: list[tuple(str, Any, Any)] = None, # if passed - this will override default field types (or add new fields)
)
```


Take this example:

```python hl_lines="2 4"
from django.contrib.auth.models import User
from ninja.orm import create_schema

UserSchema = create_schema(User)

# Will create schema like this:
# 
# class UserSchema(Schema):
#     id: int
#     username: str
#     first_name: str
#     last_name: str
#     password: str
#     last_login: datetime
#     is_superuser: bool
#     email: str
#     ... and the rest

```

!!! Warning
    By default `create_schema` builds a schema with ALL model fields.
    This can lead to accidental unwanted data exposure (like hashed password, in the above example).
    <br>
    **Always** use `fields` or `exclude` arguments to explicitly define list of attributes.

### Using `fields`

```python hl_lines="1"
UserSchema = create_schema(User, fields=['id', 'username'])

# Will create schema like this:
# 
# class UserSchema(Schema):
#     id: int
#     username: str

```

### Using `exclude`

```python hl_lines="1 2"
UserSchema = create_schema(User, exclude=[
    'password', 'last_login', 'is_superuser', 'is_staff', 'groups', 'user_permissions']
)

# Will create schema without excluded fields:
# 
# class UserSchema(Schema):
#    id: int
#    username: str
#    first_name: str
#    last_name: str
#    email: str
#    is_active: bool
#    date_joined: datetime
```

### Using `depth`

The `depth` argument allows you to introspect the Django model into the Related fields(ForeignKey, OneToOne, ManyToMany).

```python hl_lines="1 7"
UserSchema = create_schema(User, depth=1, fields=['username', 'groups'])

# Will create the following schema:
#
# class UserSchema(Schema):
#    username: str
#    groups: List[Group]
```

Note here that groups became a `List[Group]` - many2many field introspected 1 level deeper and created schema as well for group:

```python
class Group(Schema):
    id: int
    name: str
    permissions: List[int]
```


================================================
FILE: docs/docs/guides/response/django-pydantic.md
================================================
# Schemas from Django models


Schemas are very useful to define your validation rules and responses, but sometimes you need to reflect your database models into schemas and keep changes in sync.

## ModelSchema 

`ModelSchema` is a special base class that can automatically generate schemas from your models.

All you need is to set `model` and `fields` attributes on your schema `Meta`:


```python hl_lines="2 5 6 7"
from django.contrib.auth.models import User
from ninja import ModelSchema

class UserSchema(ModelSchema):
    class Meta:
        model = User
        fields = ['id', 'username', 'first_name', 'last_name']

# Will create schema like this:
# 
# class UserSchema(Schema):
#     id: int
#     username: str
#     first_name: str
#     last_name: str
```

!!! note

    You can also specify the model using a [Django Absolute Lazy relationship](https://docs.djangoproject.com/en/stable/ref/models/fields/#absolute).
    In the above example, it would be `model = 'auth.User'`.


### Using ALL model fields

To use all fields from a model - you can pass `__all__` to `fields`:

```python hl_lines="4"
class UserSchema(ModelSchema):
    class Meta:
        model = User
        fields = "__all__"
```
!!! Warning
    Using __all__ is not recommended.
    <br>
    This can lead to accidental unwanted data exposure (like hashed password, in the above example).
    <br>
    General advice - use `fields` to explicitly define list of fields that you want to be visible in API.

### Excluding model fields

To use all fields **except** a few, you can use `exclude` configuration:

```python hl_lines="4"
class UserSchema(ModelSchema):
    class Meta:
        model = User
        exclude = ['password', 'last_login', 'user_permissions']

# Will create schema like this:
# 
# class UserSchema(Schema):
#     id: int
#     username: str
#     first_name: str
#     last_name: str
#     email: str
#     is_superuser: bool
#     ... and the rest

```

### Overriding fields

To change default annotation for some field, or to add a new field, just use annotated attributes as usual. 

```python hl_lines="1 2 3 4 8"
class GroupSchema(ModelSchema):
    class Meta:
        model = Group
        fields = ['id', 'name']


class UserSchema(ModelSchema):
    groups: List[GroupSchema] = []

    class Meta:
        model = User
        fields = ['id', 'username', 'first_name', 'last_name']

```


### Making fields optional

Pretty often for PATCH API operations you need to make all fields of your schema optional. To do that, you can use config fields_optional

```python hl_lines="5"
class PatchGroupSchema(ModelSchema):
    class Meta:
        model = Group
        fields = ['id', 'name', 'description'] # Note: all these fields are required on model level
        fields_optional = '__all__'
```

Also, you can define a subset of optional fields instead of `__all__`:

```python
     fields_optional = ['description']
```

When you process input data, you need to tell Pydantic to avoid setting undefined fields to `None`:

```python
@api.patch("/patch/{pk}")
def patch(request, pk: int, payload: PatchGroupSchema):

    # Notice that we set exclude_unset=True
    updated_fields = payload.dict(exclude_unset=True)

    obj = MyModel.objects.get(pk=pk)

    for attr, value in updated_fields.items():
        setattr(obj, attr, value)

    obj.save()


```


### Custom fields types

For each Django field it encounters, `ModelSchema` uses the default `Field.get_internal_type` method
to find the correct representation in Pydantic schema (python type). This process works fine for the built-in field
types, but there are cases where the user wants to create or use a custom field, with its own mapping to
python type. In this case you should use `register_field` method to tell django-ninja which type should this django field represent:

```python hl_lines="4 7 8 9"
# models.py

class MyModel(models.Model):
    embedding = pgvector.VectorField()

# schemas.py
from ninja.orm import register_field

register_field('VectorField', list[float])

```

#### PatchDict

Another way to work with patch request data is a `PatchDict` container which allows you to make 
a schema with all optional fields and get a dict with **only** fields that was provide

```Python hl_lines="1 11"
from ninja import PatchDict

class GroupSchema(Schema):
    # You do not have to make fields optional it will be converted by PatchDict
    name: str
    description: str
    due_date: date


@api.patch("/patch/{pk}")
def modify_data(request, pk: int, payload: PatchDict[GroupSchema]):
    obj = MyModel.objects.get(pk=pk)

    for attr, value in payload.items():
        setattr(obj, attr, value)
    
    obj.save()

```

in this example the `payload` argument will be of type `dict` and only contain fields that were passed in the request and validated using `GroupSchema`


================================================
FILE: docs/docs/guides/response/index.md
================================================
# Response Schema

**Django Ninja** allows you to define the schema of your responses both for validation and documentation purposes.

Imagine you need to create an API operation that creates a user. The **input** parameter would be **username+password**, but **output** of this operation should be **id+username** (**without** the password).

Let's create the input schema:

```python hl_lines="3 5"
from ninja import Schema

class UserIn(Schema):
    username: str
    password: str


@api.post("/users/")
def create_user(request, data: UserIn):
    user = User(username=data.username) # User is django auth.User
    user.set_password(data.password)
    user.save()
    # ... return ?
```

Now let's define the output schema, and pass it as a `response` argument to the `@api.post` decorator:

```python hl_lines="8 9 10 13 18"
from ninja import Schema

class UserIn(Schema):
    username: str
    password: str


class UserOut(Schema):
    id: int
    username: str


@api.post("/users/", response=UserOut)
def create_user(request, data: UserIn):
    user = User(username=data.username)
    user.set_password(data.password)
    user.save()
    return user
```

**Django Ninja** will use this `response` schema to:

- convert the output data to declared schema
- validate the data
- add an OpenAPI schema definition
- it will be used by the automatic documentation systems
- and, most importantly, it **will limit the output data** only to the fields only defined in the schema.

## Nested objects

There is also often a need to return responses with some nested/child objects.

Imagine we have a `Task` Django model with a `User` ForeignKey:

```python hl_lines="6"
from django.db import models

class Task(models.Model):
    title = models.CharField(max_length=200)
    is_completed = models.BooleanField(default=False)
    owner = models.ForeignKey("auth.User", null=True, blank=True)
```

Now let's output all tasks, and for each task, output some fields about the user.

```python hl_lines="13 16"
from typing import List
from ninja import Schema

class UserSchema(Schema):
    id: int
    first_name: str
    last_name: str

class TaskSchema(Schema):
    id: int
    title: str
    is_completed: bool
    owner: UserSchema = None  # ! None - to mark it as optional


@api.get("/tasks", response=List[TaskSchema])
def tasks(request):
    queryset = Task.objects.select_related("owner")
    return list(queryset)
```

If you execute this operation, you should get a response like this:

```JSON hl_lines="6 7 8 9 16"
[
    {
        "id": 1,
        "title": "Task 1",
        "is_completed": false,
        "owner": {
            "id": 1,
            "first_name": "John",
            "last_name": "Doe",
        }
    },
    {
        "id": 2,
        "title": "Task 2",
        "is_completed": false,
        "owner": null
    },
]
```

## Aliases

Instead of a nested response, you may want to just flatten the response output.
The Ninja `Schema` object extends Pydantic's `Field(..., alias="")` format to
work with dotted responses.

Using the models from above, let's make a schema that just includes the task
owner's first name inline, and also uses `completed` rather than `is_completed`:

```python hl_lines="1 7-9"
from ninja import Field, Schema


class TaskSchema(Schema):
    id: int
    title: str
    # The first Field param is the default, use ... for required fields.
    completed: bool = Field(..., alias="is_completed")
    owner_first_name: str = Field(None, alias="owner.first_name")
```

Aliases also support django template syntax variables access:

```python hl_lines="2"
class TaskSchema(Schema):
    last_message: str = Field(None, alias="message_set.0.text")
```

```python hl_lines="3"
class TaskSchema(Schema):
    type: str = Field(None)
    type_display: str = Field(None, alias="get_type_display") # callable will be executed
```

## Resolvers

You can also create calculated fields via resolve methods based on the field
name.

The method must accept a single argument, which will be the object the schema
is resolving against.

When creating a resolver as a standard method, `self` gives you access to other
validated and formatted attributes in the schema.

```python hl_lines="5 7-11"
class TaskSchema(Schema):
    id: int
    title: str
    is_completed: bool
    owner: Optional[str] = None
    lower_title: str

    @staticmethod
    def resolve_owner(obj):
        if not obj.owner:
            return
        return f"{obj.owner.first_name} {obj.owner.last_name}"

    def resolve_lower_title(self, obj):
        return self.title.lower()
```

### Accessing extra context

Pydantic v2 allows you to process an extra context that is passed to the serializer. In the following example you can have resolver that gets request object from passed `context` argument:

```python hl_lines="6"
class Data(Schema):
    a: int
    path: str = ""

    @staticmethod
    def resolve_path(obj, context):
        request = context["request"]
        return request.path
```

if you use this schema for incoming requests - the `request` object will be automatically passed to context.

You can as well pass your own context:

```python
data = Data.model_validate({'some': 1}, context={'request': MyRequest()})
```

## Returning querysets

In the previous example we specifically converted a queryset into a list (and executed the SQL query during evaluation).

You can avoid that and return a queryset as a result, and it will be automatically evaluated to List:

```python hl_lines="3"
@api.get("/tasks", response=List[TaskSchema])
def tasks(request):
    return Task.objects.all()
```

!!! warning

    If your operation is async, this example will not work because the ORM query needs to be called safely.

    ```python hl_lines="2"
    @api.get("/tasks", response=List[TaskSchema])
    async def tasks(request):
        return Task.objects.all()
    ```

    See the [async support](../async-support.md#using-orm) guide for more information.

## FileField and ImageField

**Django Ninja** by default converts files and images (declared with `FileField` or `ImageField`) to `string` URL's.

An example:

```python hl_lines="3"
class Picture(models.Model):
    title = models.CharField(max_length=100)
    image = models.ImageField(upload_to='images')
```

If you need to output to response image field, declare a schema for it as follows:

```python hl_lines="3"
class PictureSchema(Schema):
    title: str
    image: str
```

Once you output this to a response, the URL will be automatically generated for each object:

```JSON
{
    "title": "Zebra",
    "image": "/static/images/zebra.jpg"
}
```

## Multiple Response Schemas

Sometimes you need to define more than response schemas.
In case of authentication, for example, you can return:

- **200** successful -> token
- **401** -> Unauthorized
- **402** -> Payment required
- **403** -> Forbidden
- etc..

In fact, the [OpenAPI specification](https://swagger.io/docs/specification/describing-responses/) allows you to pass multiple response schemas.

You can pass to a `response` argument a dictionary where:

- key is a response code
- value is a schema for that code

Also, when you return the result - you have to also pass a status code to tell **Django Ninja** which schema should be used for validation and serialization.

An example:

```python hl_lines="1 9 12 14 16"
from ninja import Status

class Token(Schema):
    token: str
    expires: date

class Message(Schema):
    message: str


@api.post('/login', response={200: Token, 401: Message, 402: Message})
def login(request, payload: Auth):
    if auth_not_valid:
        return Status(401, {'message': 'Unauthorized'})
    if negative_balance:
        return Status(402, {'message': 'Insufficient balance amount. Please proceed to a payment page.'})
    return Status(200, {'token': xxx, ...})
```

!!! warning "Deprecated: tuple syntax"
    Returning `(status_code, body)` tuples is deprecated and will be removed in a future version.
    Use `Status(status_code, body)` instead.

## Multiple response codes

In the previous example you saw that we basically repeated the `Message` schema twice:

```
...401: Message, 402: Message}
```

To avoid this duplication you can use multiple response codes for a schema:

```python hl_lines="2 3 6 9 11"
...
from ninja import Status
from ninja.responses import codes_4xx


@api.post('/login', response={200: Token, codes_4xx: Message})
def login(request, payload: Auth):
    if auth_not_valid:
        return Status(401, {'message': 'Unauthorized'})
    if negative_balance:
        return Status(402, {'message': 'Insufficient balance amount. Please proceed to a payment page.'})
    return Status(200, {'token': xxx, ...})
```

**Django Ninja** comes with the following HTTP codes:

```python
from ninja.responses import codes_1xx
from ninja.responses import codes_2xx
from ninja.responses import codes_3xx
from ninja.responses import codes_4xx
from ninja.responses import codes_5xx
```

You can also create your own range using a `frozenset`:

```python
my_codes = frozenset({416, 418, 425, 429, 451})

@api.post('/login', response={200: Token, my_codes: Message})
def login(request, payload: Auth):
    ...
```

## Empty responses

Some responses, such as [204 No Content](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204), have no body.
To indicate the response body is empty mark `response` argument with `None` instead of Schema:

```python hl_lines="1 3"
@api.post("/no_content", response={204: None})
def no_content(request):
    return Status(204, None)
```

## Error responses

Check [Handling errors](../errors.md) for more information.

## Self-referencing schemes

Sometimes you need to create a schema that has reference to itself, or tree-structure objects.

To do that you need:

- set a type of your schema in quotes
- use `model_rebuild` method to apply self referencing types

```python hl_lines="3 6"
class Organization(Schema):
    title: str
    part_of: 'Organization' = None     #!! note the type in quotes here !!


Organization.model_rebuild()  # !!! this is important


@api.get('/organizations', response=List[Organization])
def list_organizations(request):
    ...
```

## Self-referencing schemes from `create_schema()`

To be able to use the method `model_rebuild()` from a schema generated via `create_schema()`,
the "name" of the class needs to be in our namespace. In this case it is very important to pass
the `name` parameter to `create_schema()`

```python hl_lines="3"
UserSchema = create_schema(
    User,
    name='UserSchema',  # !!! this is important for model_rebuild()
    fields=['id', 'username']
    custom_fields=[
        ('manager', 'UserSchema', None),
    ]
)
UserSchema.model_rebuild()
```

## Serializing Outside of Views

Serialization of your objects can be done directly in code through the use of
the `.from_orm()` method on the schema object.

Consider the following model:

```python
class Person(models.Model):
    name = models.CharField(max_length=50)
```

Which can be accessed using this schema:

```python
class PersonSchema(Schema):
    name: str
```

Direct serialization can be performed using the `.from_orm()` method on the
schema. Once you have an instance of the schema object, the `.dict()` and
`.json()` methods allow you to get at both dictionary output and string JSON
versions.

```python
>>> person = Person.objects.get(id=1)
>>> data = PersonSchema.from_orm(person)
>>> data
PersonSchema(id=1, name='Mr. Smith')
>>> data.dict()
{'id':1, 'name':'Mr. Smith'}
>>> data.json()
'{"id":1, "name":"Mr. Smith"}'
```

Multiple Items: or a queryset (or list)

```python
>>> persons = Person.objects.all()
>>> data = [PersonSchema.from_orm(i).dict() for i in persons]
[{'id':1, 'name':'Mr. Smith'},{'id': 2, 'name': 'Mrs. Smith'}...]
```

## Django HTTP responses

It is also possible to return regular django http responses:

```python
from django.http import HttpResponse
from django.shortcuts import redirect


@api.get("/http")
def result_django(request):
    return HttpResponse('some data')   # !!!!


@api.get("/something")
def some_redirect(request):
    return redirect("/some-path")  # !!!!
```


================================================
FILE: docs/docs/guides/response/pagination.md
================================================
# Pagination

**Django Ninja** comes with a pagination support. This allows you to split large result sets into individual pages.


To apply pagination to a function - just apply `paginate` decorator:

```python hl_lines="1 4"
from ninja.pagination import paginate

@api.get('/users', response=List[UserSchema])
@paginate
def list_users(request):
    return User.objects.all()
```


That's it!

Now you can query users with `limit` and `offset` GET parameters

```
/api/users?limit=10&offset=0
```

by default limit is set to `100` (you can change it in your settings.py using `NINJA_PAGINATION_PER_PAGE`)


## Built in Pagination Classes

### LimitOffsetPagination (default)

This is the default pagination class (You can change it in your settings.py using `NINJA_PAGINATION_CLASS` path to a class)

```python hl_lines="1 4"
from ninja.pagination import paginate, LimitOffsetPagination

@api.get('/users', response=List[UserSchema])
@paginate(LimitOffsetPagination)
def list_users(request):
    return User.objects.all()
```

Example query:
```
/api/users?limit=10&offset=0
```

this class has two input parameters:

 - `limit` - defines a number of queryset on the page (default = 100, change in NINJA_PAGINATION_PER_PAGE)
 - `offset` - set's the page window offset (default: 0, indexing starts with 0)


### PageNumberPagination
```python hl_lines="1 4"
from ninja.pagination import paginate, PageNumberPagination

@api.get('/users', response=List[UserSchema])
@paginate(PageNumberPagination)
def list_users(request):
    return User.objects.all()
```

Example query:
```
/api/users?page=2
```

this class has one parameter `page` and outputs 100 queryset per page by default  (can be changed with settings.py)

Page numbering start with 1

you can also set custom page_size value individually per view:

```python hl_lines="2"
@api.get("/users")
@paginate(PageNumberPagination, page_size=50)
def list_users(...
```

In addition to the `page` parameter, you can also use the `page_size` parameter to dynamically adjust the number of records displayed per page:

Example query:
```
/api/users?page=2&page_size=20
```

This allows you to temporarily override the page size setting in your request. The request will use the specified `page_size` value if provided. Otherwise, it will use either the value specified in the decorator or the value from `PAGINATION_MAX_PER_PAGE_SIZE` in settings.py if no decorator value is set.

### CursorPagination

Cursor-based pagination provides stable pagination for datasets that may change frequently. Cursor pagination uses base64 encoded tokens to mark positions in the dataset, ensuring consistent results even when items are added or removed.

```python hl_lines="1 4"
from ninja.pagination import paginate, CursorPagination

@api.get('/events', response=List[EventSchema])
@paginate(CursorPagination)
def list_events(request):
    return Event.objects.all()
```

Example query:

```
/api/events?cursor=eyJwIjoiMjAyNC0wMS0wMSIsInIiOmZhbHNlLCJvIjowfQ==
```

this class has two input parameters:

- `cursor` - base64 token representing the current position (optional, starts from beginning if not provided)
- `page_size` - number of items per page (optional)

You can specify the `page_size` value to temporarily override in the request:

```
/api/events?cursor=eyJwIjoiMjAyNC0wMS0wMSIsInIiOmZhbHNlLCJvIjowfQ==&page_size=5
```

This class has a few parameters, which determine how the cursor position is ascertained and the parameter encoded:

- `ordering` - tuple of field names to order the queryset. Use `-` prefix for descending order. The first one of which will be used to encode the position. The ordering field should be unique if possible. A string representation of this field will be used to point to the current position of the cursor. Timestamps work well if each item in the collection is created independently. The paginator can handle some non-uniqueness by adding an offset. Defaults to `("-pk",)`, change in `NINJA_PAGINATION_DEFAULT_ORDERING`

- `page_size` - default page size for endpoint. Defaults to `100`, change in `NINJA_PAGINATION_PER_PAGE`
- `max_page_size` - maximum allowed page size for endpoint. Defaults to `100`, change in `NINJA_PAGINATION_MAX_PER_PAGE_SIZE`

Finally, there is a `NINJA_PAGINATION_MAX_OFFSET` setting to limit malicious cursor requests. It defaults to `100`.

The class parameters can be set globally via settings as well as per view:

```python hl_lines="2"
@api.get("/events")
@paginate(CursorPagination, ordering=("start_date", "end_date"), page_size=20, max_page_size=100)
def list_events(request):
    return Event.objects.all()
```

The response includes navigation links and results:

```json
{
  "next": "http://api.example.com/events?cursor=eyJwIjoiMjAyNC0wMS0wMiIsInIiOmZhbHNlLCJvIjowfQ==",
  "previous": "http://api.example.com/events?cursor=eyJwIjoiMjAyNC0wMS0wMSIsInIiOnRydWUsIm8iOjB9",
  "results": [
    { "id": 1, "title": "Event 1", "start_date": "2024-01-01" },
    { "id": 2, "title": "Event 2", "start_date": "2024-01-02" }
  ]
}
```

## Accessing paginator parameters in view function

If you need access to `Input` parameters used for pagination in your view function - use `pass_parameter` argument

In that case input data will be available in `**kwargs`:

```python hl_lines="2 4"
@api.get("/someview")
@paginate(pass_parameter="pagination_info")
def someview(request, **kwargs):
    page = kwargs["pagination_info"].page
    return ...
```


## Creating Custom Pagination Class

To create a custom pagination class you should subclass `ninja.pagination.PaginationBase` and override the `Input` and `Output` schema classes and `paginate_queryset(self, queryset, request, **params)` method:

 - The `Input` schema is a Schema class that describes parameters that should be passed to your paginator (f.e. page-number or limit/offset values).
 - The `Output` schema describes schema for page output (f.e. count/next-page/items/etc).
 - The `paginate_queryset` method is passed the initial queryset and should return an iterable object that contains only the data in the requested page. This method accepts the following arguments:
    - `queryset`: a queryset (or iterable) returned by the api function
    - `pagination` - the paginator.Input parameters (parsed and validated)
    - `**params`: kwargs that will contain all the arguments that decorated function received 


Example:

```python hl_lines="7 11 16 26"
from ninja.pagination import paginate, PaginationBase
from ninja import Schema


class CustomPagination(PaginationBase):
    # only `skip` param, defaults to 5 per page
    class Input(Schema):
        skip: int
        

    class Output(Schema):
        items: List[Any] # `items` is a default attribute
        total: int
        per_page: int

    def paginate_queryset(self, queryset, pagination: Input, **params):
        skip = pagination.skip
        return {
            'items': queryset[skip : skip + 5],
            'total': queryset.count(),
            'per_page': 5,
        }


@api.get('/users', response=List[UserSchema])
@paginate(CustomPagination)
def list_users(request):
    return User.objects.all()
```

Tip: You can access request object from params:

```python
def paginate_queryset(self, queryset, pagination: Input, **params):
    request = params["request"]
```

#### Async Pagination

Standard **Django Ninja** pagination classes support async. If you wish to handle async requests with a custom pagination class, you should subclass `ninja.pagination.AsyncPaginationBase` and override the `apaginate_queryset(self, queryset, request, **params)` method.

### Output attribute

By default page items are placed to `'items'` attribute. To override this behaviour use `items_attribute`:

```python hl_lines="4 8"
class CustomPagination(PaginationBase):
    ...
    class Output(Schema):
        results: List[Any]
        total: int
        per_page: int
    
    items_attribute: str = "results"

```


## Apply pagination to multiple operations at once

There is often a case when you need to add pagination to all views that returns querysets or list

You can use a builtin router class (`RouterPaginated`) that automatically injects pagination to all operations that defined `response=List[SomeSchema]`:

```python hl_lines="1 3 6 10"
from ninja.pagination import RouterPaginated

router = RouterPaginated()


@router.get("/items", response=List[MySchema])
def items(request):
    return MyModel.objects.all()

@router.get("/other-items", response=List[OtherSchema])
def other_items(request):
    return OtherModel.objects.all()

```

In this example both operations will have pagination enabled

to apply pagination to main `api` instance use `default_router` argument:


```python
api = NinjaAPI(default_router=RouterPaginated())

@api.get(...
```


================================================
FILE: docs/docs/guides/response/response-renderers.md
================================================
# Response renderers

The most common response type for a REST API is usually JSON.
**Django Ninja** also has support for defining your own custom renderers, which gives you the flexibility to design your own media types.

## Create a renderer

To create your own renderer, you need to inherit `ninja.renderers.BaseRenderer` and override the `render` method. Then you can pass an instance of your class to `NinjaAPI` as the `renderer` argument:

```python hl_lines="5 8 9"
from ninja import NinjaAPI
from ninja.renderers import BaseRenderer


class MyRenderer(BaseRenderer):
    media_type = "text/plain"

    def render(self, request, data, *, response_status):
        return ... # your serialization here

api = NinjaAPI(renderer=MyRenderer())
```

The `render` method takes the following arguments:

 - request -> HttpRequest object 
 - data -> object that needs to be serialized
 - response_status as an `int` -> the HTTP status code that will be returned to the client

You need also define the `media_type` attribute on the class to set the content-type header for the response.


## ORJSON renderer example:

[orjson](https://github.com/ijl/orjson#orjson) is a fast, accurate JSON library for Python. It benchmarks as the fastest Python library for JSON and is more accurate than the standard `json` library or other third-party libraries. It also serializes dataclass, datetime, numpy, and UUID instances natively.

Here's an example renderer class that uses `orjson`:


```python hl_lines="9 10"
import orjson
from ninja import NinjaAPI
from ninja.renderers import BaseRenderer


class ORJSONRenderer(BaseRenderer):
    media_type = "application/json"

    def render(self, request, data, *, response_status):
        return orjson.dumps(data)

api = NinjaAPI(renderer=ORJSONRenderer())
```



## XML renderer example:


This is how you create a renderer that outputs all responses as XML:


```python hl_lines="8 11"
from io import StringIO
from django.utils.encoding import force_str
from django.utils.xmlutils import SimplerXMLGenerator
from ninja import NinjaAPI
from ninja.renderers import BaseRenderer


class XMLRenderer(BaseRenderer):
    media_type = "text/xml"

    def render(self, request, data, *, response_status):
        stream = StringIO()
        xml = SimplerXMLGenerator(stream, "utf-8")
        xml.startDocument()
        xml.startElement("data", {})
        self._to_xml(xml, data)
        xml.endElement("data")
        xml.endDocument()
        return stream.getvalue()

    def _to_xml(self, xml, data):
        if isinstance(data, (list, tuple)):
            for item in data:
                xml.startElement("item", {})
                self._to_xml(xml, item)
                xml.endElement("item")

        elif isinstance(data, dict):
            for key, value in data.items():
                xml.startElement(key, {})
                self._to_xml(xml, value)
                xml.endElement(key)

        elif data is None:
            # Don't output any value
            pass

        else:
            xml.characters(force_str(data))


api = NinjaAPI(renderer=XMLRenderer())
```
*(Copyright note: this code is basically copied from [DRF-xml](https://jpadilla.github.io/django-rest-framework-xml/))*


================================================
FILE: docs/docs/guides/response/temporal_response.md
================================================
# Altering the Response

Sometimes you'll want to change the response just before it gets served, for example, to add a header or alter a cookie.

To do this, simply declare a function parameter with a type of `HttpResponse`:

```python
from django.http import HttpRequest, HttpResponse

@api.get("/cookie/")
def feed_cookiemonster(request: HttpRequest, response: HttpResponse):
    # Set a cookie.
    response.set_cookie("cookie", "delicious")
    # Set a header.
    response["X-Cookiemonster"] = "blue"
    return {"cookiemonster_happy": True}
```


## Temporal response object

This response object is used for the base of all responses built by Django Ninja, including error responses. This object is *not* used if a Django `HttpResponse` object is returned directly by an operation.

Obviously this response object won't contain the content yet, but it does have the `content_type` set (but you probably don't want to be changing it).

The `status_code` will get overridden depending on the return value (200 by default, or the status code if a two-part tuple is returned).


## Changing the base response object

You can alter this temporal response object by overriding the `NinjaAPI.create_temporal_response` method.

```python
    def create_temporal_response(self, request: HttpRequest) -> HttpResponse:
        response = super().create_temporal_response(request)
        # Do your magic here...
        return response
```

================================================
FILE: docs/docs/guides/routers.md
================================================
# Routers

Real world applications can almost never fit all logic into a single file. 

**Django Ninja** comes with an easy way to split your API into multiple modules using Routers.

Let's say you have a Django project with a structure like this:


```
├── myproject
│   └── settings.py
├── events/
│   ├── __init__.py
│   └── models.py
├── news/
│   ├── __init__.py
│   └── models.py
├── blogs/
│   ├── __init__.py
│   └── models.py
└── manage.py
```

To add API's to each of the Django applications, create an `api.py` module in each app:

``` hl_lines="5 9 13"
├── myproject
│   └── settings.py
├── events/
│   ├── __init__.py
│   ├── api.py
│   └── models.py
├── news/
│   ├── __init__.py
│   ├── api.py
│   └── models.py
├── blogs/
│   ├── __init__.py
│   ├── api.py
│   └── models.py
└── manage.py
```

Now let's add a few operations to `events/api.py`. The trick is that instead of using the `NinjaAPI` class, you use the **Router** class:

```python  hl_lines="1 4 6 13"
from ninja import Router
from .models import Event

router = Router()

@router.get('/')
def list_events(request):
    return [
        {"id": e.id, "title": e.title}
        for e in Event.objects.all()
    ]

@router.get('/{event_id}')
def event_details(request, event_id: int):
    event = Event.objects.get(id=event_id)
    return {"title": event.title, "details": event.details}
```

Then do the same for the `news` app with `news/api.py`:

```python  hl_lines="1 4"
from ninja import Router
from .models import News

router = Router()

@router.get('/')
def list_news(request):
    ...

@router.get('/{news_id}')
def news_details(request, news_id: int):
    ...
```
and then also `blogs/api.py`.


Finally, let's group them together.
In your top level project folder (next to `urls.py`), create another `api.py` file with the main `NinjaAPI` instance:

``` hl_lines="2"
├── myproject
│   ├── api.py
│   └── settings.py
├── events/
│   ...
├── news/
│   ...
├── blogs/
│   ...

```

It should look like this:

```python
from ninja import NinjaAPI

api = NinjaAPI()

```

Now we import all the routers from the various apps, and include them into the main API instance:

```python hl_lines="2 6 7 8"
from ninja import NinjaAPI
from events.api import router as events_router

api = NinjaAPI()

api.add_router("/events/", events_router)    # You can add a router as an object
api.add_router("/news/", "news.api.router")  #   or by Python path
api.add_router("/blogs/", "blogs.api.router")
```

Now, include `api` to your urls as usual and open your browser at `/api/docs`, and you should see all your routers combined into a single API:


![Swagger UI Simple Routers](../img/simple-routers-swagger.png)


## Router authentication

Use `auth` argument to apply authenticator to all operations declared by router:

```python
api.add_router("/events/", events_router, auth=BasicAuth())
```

or using router constructor
```python
router = Router(auth=BasicAuth())
```

## Router tags

You can use `tags` argument to apply tags to all operations declared by router:

```python
api.add_router("/events/", events_router, tags=["events"])
```

or using router constructor
```python
router = Router(tags=["events"])
```


## Nested routers

There are also times when you need to split your logic up even more.
**Django Ninja** makes it possible to include a router into another router as many times as you like, and finally include the top level router into the main `api` instance.


Basically, what that means is that you have `add_router` both on the `api` instance and on the `router` instance:



```python hl_lines="7 8 9 32 33 34"
from django.contrib import admin
from django.urls import path
from ninja import NinjaAPI, Router

api = NinjaAPI()

first_router = Router()
second_router = Router()
third_router = Router()


@api.get("/add")
def add(request, a: int, b: int):
    return {"result": a + b}


@first_router.get("/add")
def add(request, a: int, b: int):
    return {"result": a + b}


@second_router.get("/add")
def add(request, a: int, b: int):
    return {"result": a + b}


@third_router.get("/add")
def add(request, a: int, b: int):
    return {"result": a + b}


second_router.add_router("l3", third_router)
first_router.add_router("l2", second_router)
api.add_router("l1", first_router)

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/", api.urls),
]
```

Now you have the following endpoints:

```
/api/add
/api/l1/add
/api/l1/l2/add
/api/l1/l2/l3/add
```

Great! Now go have a look at the automatically generated docs:

![Swagger UI Nested Routers](../img/nested-routers-swagger.png)

### Nested url parameters

You can also use url parameters in nested routers by adding `= Path(...)` to the function parameters:

```python hl_lines="13 16"
from django.contrib import admin
from django.urls import path
from ninja import NinjaAPI, Path, Router

api = NinjaAPI()
router = Router()

@api.get("/add/{a}/{b}")
def add(request, a: int, b: int):
    return {"result": a + b}

@router.get("/multiply/{c}")
def multiply(request, c: int, a: int = Path(...), b: int = Path(...)):
    return {"result": (a + b) * c}

api.add_router("add/{a}/{b}", router)

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/", api.urls),
]
```

This will generate the following endpoints:

```
/api/add/{a}/{b}
/api/add/{a}/{b}/multiply/{c}
```

================================================
FILE: docs/docs/guides/testing.md
================================================
# Testing

**Django Ninja** is fully compatible with standard [django test client](https://docs.djangoproject.com/en/dev/topics/testing/tools/) , but also provides a test client to make it easy to test just APIs without middleware/url-resolver layer making tests run faster.

To test the following API:
```python
from ninja import NinjaAPI, Schema

api = NinjaAPI()
router = Router()

class HelloResponse(Schema):
    msg: str
    
@router.get("/hello", response=HelloResponse)
def hello(request):
    return {"msg": "Hello World"}

api.add_router("", router)
```

You can use the Django test class:
```python
from django.test import TestCase
from ninja.testing import TestClient

class HelloTest(TestCase):
    def test_hello(self):
        # don't forget to import router from code above
        client = TestClient(router)
        response = client.get("/hello")
        
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json(), {"msg": "Hello World"})
```

It is also possible to access the deserialized data using the `data` property:
```python
    self.assertEqual(response.data, {"msg": "Hello World"})
```

## Attributes
Arbitrary attributes can be added to the request object by passing keyword arguments to the client request methods:
```python
class HelloTest(TestCase):
    def test_hello(self):
        client = TestClient(router)
        # request.company_id will now be set within the view
        response = client.get("/hello", company_id=1)
```

### Headers
It is also possible to specify headers, both from the TestCase instantiation and the actual request:
```python
    client = TestClient(router, headers={"A": "a", "B": "b"})
    # The request will be made with {"A": "na", "B": "b", "C": "nc"} headers
    response = client.get("/test-headers", headers={"A": "na", "C": "nc"})
```

### Cookies
It is also possible to specify cookies, both from the TestCase instantiation and the actual request:
```python
    client = TestClient(router, COOKIES={"A": "a", "B": "b"})
    # The request will be made with {"A": "na", "B": "b", "C": "nc"} cookies
    response = client.get("/test-cookies", COOKIES={"A": "na", "C": "nc"})
```

### Users
It is also possible to specify a User for the request:
```python
    user = User.objects.create(...)
    client = TestClient(router)
    # The request will be made with user logged in
    response = client.get("/test-with-user", user=user)
```

## Testing async operations

To test operations in async context use `TestAsyncClient`:

```python
from ninja.testing import TestAsyncClient

client = TestAsyncClient(router)
response = await client.post("/test/")

```


================================================
FILE: docs/docs/guides/throttling.md
================================================
# Throttling

Throttles allows to control the rate of requests that clients can make to an API. Django Ninja allows to set custom throttlers globally (across all operations in NinjaAPI instance), on router level and each operation individually.

!!! note
    The application-level throttling that Django Ninja provides should not be considered a security measure or protection against brute forcing or denial-of-service attacks. Deliberately malicious actors will always be able to spoof IP origins. The built-in throttling implementations are implemented using Django's cache framework, and use non-atomic operations to determine the request rate, which may sometimes result in some fuzziness.


Django Ninja’s throttling feature is pretty much based on what Django Rest Framework (DRF) uses, which you can check out [here](https://www.django-rest-framework.org/api-guide/throttling/). So, if you’ve already got custom throttling set up for DRF, there’s a good chance it’ll work with Django Ninja right out of the box. The key difference is that you need to pass initialized Throttle objects instead of classes (which should give a better performance).

You can specify a rate using the format requests/time-unit, where time-unit represents a number of units followed by an optional unit of time. If the unit is omitted, it defaults to seconds. For example, the following are equivalent and all represent "100 requests per 5 minutes":

    * 100/5m
    * 100/300s
    * 100/300

The following units are supported:

    * `s` or `sec`
    * `m` or `min`
    * `h` or `hour`
    * `d` or `day`

## Usage

### Global

The following example will limit unauthenticated users to only 10 requests per second, while authenticated can make 100/s

```Python
from ninja.throttling import AnonRateThrottle, AuthRateThrottle

api = NinjaAPI(
    throttle=[
        AnonRateThrottle('10/s'),
        AuthRateThrottle('100/s'),
    ],
)
```

!!! tip
    `throttle` argument accepts single object and list of throttle objects

### Router level

Pass `throttle` argument either to `add_router` function

```Python
api = NinjaAPI()
...

api.add_router('/sensitive', 'myapp.api.router', throttle=AnonRateThrottle('100/m'))
```

or directly to init of the Router class:

```Python
router = Router(..., throttle=[AnonRateThrottle('1000/h')])
```


### Operation level

If `throttle` argument is passed to operation - it will overrule all global and router throttles:

```Python
from ninja.throttling import UserRateThrottle

@api.get('/some', throttle=[UserRateThrottle('10000/d')])
def some(request):
    ...
```

## Builtin throttlers

### AnonRateThrottle

Will only throttle unauthenticated users. The IP address of the incoming request is used to generate a unique key to throttle against.


### UserRateThrottle

Will throttle users (**if you use django build-in user authentication**) to a given rate of requests across the API. The user id is used to generate a unique key to throttle against. Unauthenticated requests will fall back to using the IP address of the incoming request to generate a unique key to throttle against.

### AuthRateThrottle

Will throttle by Django ninja [authentication](authentication.md) to a given rate of requests across the API.  Unauthenticated requests will fall back to using the IP address of the incoming request to generate a unique key to throttle against.

Note: the cache key in case of `request.auth` will be generated by `sha256(str(request.auth))` - so if you returning some custom objects inside authentication make sure to implement `__str__` method that will return a unique value for the user.


## Custom throttles
To create a custom throttle, override `BaseThrottle` (or any of builtin throttles) and implement `.allow_request(self, request)`. The method should return `True` if the request should be allowed, and `False` otherwise.

Example

```Python
from ninja.throttling import AnonRateThrottle

class NoReadsThrottle(AnonRateThrottle):
    """Do not throttle GET requests"""
    
    def allow_request(self, request):
        if request.method == "GET":
            return True
        return super().allow_request(request)
```


================================================
FILE: docs/docs/guides/urls.md
================================================
# Reverse Resolution of URLS

A reverse URL name is generated for each method in a Django Ninja Schema (or `Router`).

## How URLs are generated

The URLs are all contained within a namespace, which defaults to `"api-1.0.0"`, and each URL name matches the function it is decorated. 

For example:

```python
api = NinjaAPI()

@api.get("/")
def index(request):
    ...

index_url = reverse_lazy("api-1.0.0:index")
```

This implicit URL name will only be set for the first operation for each API path.  If you *don't* want any implicit reverse URL name generated, just explicitly specify `url_name=""` (an empty string) on the method decorator.

### Changing the URL name

Rather than using the default URL name, you can specify it explicitly as a property on the method decorator.

```python
@api.get("/users", url_name="user_list")
def users(request):
    ...

users_url = reverse_lazy("api-1.0.0:user_list")
```

This will override any implicit URL name to this API path.


#### Overriding default url names

You can also override implicit url naming by overwriting the `get_operation_url_name` method:

```python
class MyAPI(NinjaAPI):
    def get_operation_url_name(self, operation, router):
        return operation.view_func.__name__ + '_my_extra_suffix'

api = MyAPI()
```

### Customizing the namespace

The default URL namespace is built by prepending the Schema's version with `"api-"`, however you can explicitly specify the namespace by overriding the `urls_namespace` attribute of the `NinjaAPI` Schema class.

```python

api = NinjaAPI(auth=token_auth, version='2')
api_private = NinjaAPI(auth=session_auth, urls_namespace='private_api')

api_users_url = reverse_lazy("api-2:users")
private_api_admins_url = reverse_lazy("private_api:admins")
```


================================================
FILE: docs/docs/guides/versioning.md
================================================
# Versioning

## Different API version numbers

With **Django Ninja** it's easy to run multiple API versions from a single Django project.

All you have to do is create two or more NinjaAPI instances with different `version` arguments:


**api_v1.py**:

```python hl_lines="4"
from ninja import NinjaAPI


api = NinjaAPI(version='1.0.0')

@api.get('/hello')
def hello(request):
    return {'message': 'Hello from V1'}

```


api_**v2**.py:

```python hl_lines="4"
from ninja import NinjaAPI


api = NinjaAPI(version='2.0.0')

@api.get('/hello')
def hello(request):
    return {'message': 'Hello from V2'}
```


and then in **urls.py**:

```python hl_lines="8 9"
...
from api_v1 import api as api_v1
from api_v2 import api as api_v2


urlpatterns = [
    ...
    path('api/v1/', api_v1.urls),
    path('api/v2/', api_v2.urls),
]

```


Now you can go to different OpenAPI docs pages for each version:

 - http://127.0.0.1/api/**v1**/docs
 - http://127.0.0.1/api/**v2**/docs



## Different business logic

In the same way, you can define a different API for different components or areas:

```python hl_lines="4 7"
...


api = NinjaAPI(auth=token_auth, urls_namespace='public_api')
...

api_private = NinjaAPI(auth=session_auth, urls_namespace='private_api')
...


urlpatterns = [
    ...
    path('api/', api.urls),
    path('internal-api/', api_private.urls),
]

```
!!! note
    If you use different **NinjaAPI** instances, you need to define different `version`s or different `urls_namespace`s.


================================================
FILE: docs/docs/help.md
================================================
# Help / Get Help

## Do you like Django Ninja?

If you like this project, there is a tiny thing you can do to let us know that we're moving in the right direction.

Simply give django-ninja a <a href="https://github.com/vitalik/django-ninja" target="_blank">star on github</a> <a href="https://github.com/vitalik/django-ninja" target="_blank">![github star](img/github-star.png)</a>

or share this URL on social media: 
```
https://django-ninja.dev
```
Follow updates on twitter <a href="https://twitter.com/django_ninja">@django_ninja</a>

## Do you want to help us?

Pull requests are always welcome.

You can inspect our docs for typos and spelling mistakes, and create pull requests or <a href="https://github.com/vitalik/django-ninja/issues" target="_blank">open an issue</a>.

If you have any suggestions to improve **Django Ninja**, please create them as <a href="https://github.com/vitalik/django-ninja/issues" target="_blank">issues</a> on GitHub.


## Do you need help?

Do not hesitate.  Go to <a href="https://github.com/vitalik/django-ninja/issues" target="_blank">GitHub issues</a> and describe your question or problem.  We'll attempt to address them quickly.

Join the chat at our <a href="https://discord.gg/dgE4SNUDTB" target="_blank">Discord</a> server.

[Code-on the webdesign and web development company](https://code-on.be/) gives commercial consulting for Django-Ninja. If you are looking for support please contact Code-on and we will be in touch with you soon.


================================================
FILE: docs/docs/index.md
================================================
# Django Ninja - Fast Django REST Framework

<div style="background-color: black; color: red; font-size: 16px; padding: 8px;">
 RUSSIA INVADED UKRAINE - <a href="https://github.com/vitalik/django-ninja/issues/383">Please read</a>
</div>


![Django Ninja](img/hero.png)

Django Ninja is a web framework for building APIs with Django and Python 3.6+ type hints.

Key features:

 - **Easy**: Designed to be easy to use and intuitive.
 - **FAST execution**: Very high performance thanks to **<a href="https://pydantic-docs.helpmanual.io" target="_blank">Pydantic</a>** and **<a href="guides/async-support/">async support</a>**. 
 - **Fast to code**: Type hints and automatic docs lets you focus only on business logic.
 - **Standards-based**: Based on the open standards for APIs: **OpenAPI** (previously known as Swagger) and **JSON Schema**.
 - **Django friendly**: (obviously) has good integration with the Django core and ORM.
 - **Production ready**: Used by multiple companies on live projects (If you use Django Ninja and would like to publish your feedback, please email ppr.vitaly@gmail.com).

<a href="https://github.com/vitalik/django-ninja-benchmarks" target="_blank">Benchmarks</a>:

![Django Ninja REST Framework](img/benchmark.png)

## Installation

```
pip install django-ninja
```

## Quick Example

Start a new Django project (or use an existing one)
```
django-admin startproject apidemo
```

in `urls.py`

```python hl_lines="3 5 8 9 10 15"
{!./src/index001.py!}
```

Now, run it as usual:
```
./manage.py runserver
```

Note: You don't have to add Django Ninja to your installed apps for it to work.

## Check it

Open your browser at <a href="http://127.0.0.1:8000/api/add?a=1&b=2" target="_blank">http://127.0.0.1:8000/api/add?a=1&b=2</a>

You will see the JSON response as:
```JSON
{"result": 3}
```
Now you've just created an API that:

 - receives an HTTP GET request at `/api/add`
 - takes, validates and type-casts GET parameters `a` and `b`
 - decodes the result to JSON
 - generates an OpenAPI schema for defined operation

## Interactive API docs

Now go to <a href="http://127.0.0.1:8000/api/docs" target="_blank">http://127.0.0.1:8000/api/docs</a>

You will see the automatic, interactive API documentation (provided by the <a href="https://github.com/swagger-api/swagger-ui" target="_blank">OpenAPI / Swagger UI</a> or <a href="https://github.com/Redocly/redoc" target="_blank">Redoc</a>):

![Swagger UI](img/index-swagger-ui.png)


## Recap

In summary, you declare the types of parameters, body, etc. **once only**, as function parameters. 

You do that with standard modern Python types.

You don't have to learn a new syntax, the methods or classes of a specific library, etc.

Just standard **Python 3.6+**.

For example, for an `int`:

```python
a: int
```

or, for a more complex `Item` model:

```python
class Item(Schema):
    foo: str
    bar: float

def operation(a: Item):
    ...
```

... and with that single declaration you get:

* Editor support, including:
    * Completion
    * Type checks
* Validation of data:
    * Automatic and clear errors when the data is invalid
    * Validation, even for deeply nested JSON objects
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data coming from the network, to Python data and types, and reading from:
    * JSON
    * Path parameters
    * Query parameters
    * Cookies
    * Headers
    * Forms
    * Files
* Automatic, interactive API documentation

This project was heavily inspired by <a href="https://fastapi.tiangolo.com/" target="_blank">FastAPI</a> (developed by <a href="https://github.com/tiangolo" target="_blank">Sebastián Ramírez</a>)



================================================
FILE: docs/docs/javascripts/ask-ai-button.js
================================================
// Add "Ask AI" button to the Material for MkDocs navbar
document.addEventListener('DOMContentLoaded', function() {
    // Find the header navigation actions (right side of navbar)
    const headerActions = document.querySelector('.md-header__topic + .md-header__option');
    const headerTitle = document.querySelector('.md-header__title');

    if (headerTitle) {
        // Create the Ask AI button
        const askAiButton = document.createElement('a');
        askAiButton.href = '/chat';  // Update this URL to your desired destination
        askAiButton.className = 'md-button ask-ai-button';
        askAiButton.textContent = 'Ask AI';
        askAiButton.title = 'Ask AI about Django Ninja';

        // Create a container for the button
        const buttonContainer = document.createElement('div');
        buttonContainer.className = 'ask-ai-button-container';
        buttonContainer.appendChild(askAiButton);

        // Insert the button after the header title
        const header = document.querySelector('.md-header__inner');
        if (header) {
            // Find the right spot - after title, before search/repo buttons
            const source = document.querySelector('.md-header__source');
            if (source) {
                header.insertBefore(buttonContainer, source);
            } else {
                header.appendChild(buttonContainer);
            }
        }
    }
});


================================================
FILE: docs/docs/motivation.md
================================================
# Motivation

!!! quote
    **Django Ninja** looks basically the same as **FastAPI**, so why not just use FastAPI?

Indeed, **Django Ninja** is heavily inspired by <a href="https://fastapi.tiangolo.com/" target="_blank">FastAPI</a> (developed by <a href="https://github.com/tiangolo" target="_blank">Sebastián Ramírez</a>)

That said, there are few issues when it comes to getting FastAPI and Django to work together properly:

1) **FastAPI** declares to be ORM agnostic (meaning you can use it with SQLAlchemy or the Django ORM), but in reality the Django ORM is not yet ready for async use (it may be in version 4.0 or 4.1), and if you use it in sync mode, you can have a [closed connection issue](https://github.com/tiangolo/fastapi/issues/716) which you will have to overcome with a **lot** of effort.

2) The dependency injection with arguments makes your code too verbose when you rely on authentication and database sessions in your operations (which for some projects is about 99% of all operations).

```python hl_lines="25 26"
...

app = FastAPI()


# Dependency
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


async def get_current_user(token: str = Depends(oauth2_scheme)):
    user = decode(token)
    if not user:
        raise HTTPException(...)
    return user


@app.get("/task/{task_id}", response_model=Task)
def read_user(
        task_id: int,
        db: Session = Depends(get_db), 
        current_user: User = Depends(get_current_user),
    ):
        ... use db with current_user ....
```

3) Since the word `model` in Django is "reserved" for use by the ORM, it becomes very confusing when you mix the Django ORM with Pydantic/FastAPI model naming conventions. 

### Django Ninja

Django Ninja addresses all those issues, and integrates very well with Django (ORM, urls, views, auth and more)

Working at [Code-on a Django webdesign webedevelopment studio](https://code-on.be/) I get all sorts of challenges and to solve these I started Django-Ninja in 2020.

Note: **Django Ninja is a production ready project** - my estimation is at this time already 100+ companies using it in production and 500 new developers joining every month. 

Some companies are already looking for developers with django ninja experience.

#### Main Features

1) Since you can have multiple Django Ninja API instances - you can run [multiple API versions](guides/versioning.md) inside one Django project.

```python
api_v1 = NinjaAPI(version='1.0', auth=token_auth)
...
api_v2 = NinjaAPI(version='2.0', auth=token_auth)
...
api_private = NinjaAPI(auth=session_auth, urls_namespace='private_api')
...


urlpatterns = [
    ...
    path('api/v1/', api_v1.urls),
    path('api/v2/', api_v2.urls),
    path('internal-api/', api_private.urls),
]
```

2) The Django Ninja 'Schema' class is integrated with the ORM, so you can [serialize querysets](guides/response/index.md#returning-querysets) or ORM objects:

```python
@api.get("/tasks", response=List[TaskSchema])
def tasks(request):
    return Task.objects.all()


@api.get("/tasks", response=TaskSchema)
def tasks_details(request):
    task = Task.objects.first()
    return task
```
3) [Create Schema's from Django Models](guides/response/django-pydantic.md).

4) Instead of dependency arguments, **Django Ninja** uses `request` instance attributes (in the same way as regular Django views) - more detail at [Authentication](guides/authentication.md).


================================================
FILE: docs/docs/proposals/cbv.md
================================================
# Class Based Operations


!!! warning ""
    This is just a proposal and it is **not present in library code**, but eventually this can be a part of Django Ninja.

    Please consider adding likes/dislikes or comments in [github issue](https://github.com/vitalik/django-ninja/issues/15) to express your feeling about this proposal


## Problem

An API operation is a callable which takes a request and parameters and returns a response, but it is often a case in real world when you need to reuse the same pieces of code in multiple operations.

Let's take the following example:

 - we have a Todo application with Projects and Tasks
 - each project has multiple tasks
 - each project may also have an owner (user)
 - users should not be able to access projects they do not own

Model structure is something like this:

```python
class Project(models.Model):
    title = models.CharField(max_length=100)
    owner = models.ForeignKey('auth.User', on_delete=models.CASCADE)

class Task(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    completed = models.BooleanField()
```


Now, let's create a few API operations for it:

 - a list of tasks for the project
 - some task details
 - a 'complete task' action

The code should validate that a user can only access his/her own project's tasks (otherwise, return 404)

It can be something like this:


```python
router = Router()

@router.get('/project/{project_id}/tasks/', response=List[TaskOut])
def task_list(request):
    user_projects = request.user.project_set
    project = get_object_or_404(user_projects, id=project_id))
    return project.task_set.all()

@router.get('/project/{project_id}/tasks/{task_id}/', response=TaskOut)
def details(request, task_id: int):
    user_projects = request.user.project_set
    project = get_object_or_404(user_projects, id=project_id))
    user_tasks = project.task_set.all()
    return get_object_or_404(user_tasks, id=task_id)


@router.post('/project/{project_id}/tasks/{task_id}/complete', response=TaskOut)
def complete(request, task_id: int):
    user_projects = request.user.project_set
    project = get_object_or_404(user_projects, id=project_id))
    user_tasks = project.task_set.all()
    task = get_object_or_404(user_tasks, id=task_id)
    task.completed = True
    task.save()
    return task
```


As you can see, these lines are getting repeated pretty often to check permission:

```python hl_lines="1 2"
user_projects = request.user.project_set
project = get_object_or_404(user_projects, id=project_id))
```

You can extract it to a function, but it will just make it 3 lines smaller, and it will still be pretty polluted ...


## Solution

The proposal is to have alternative called "Class Based Operation" where you can decorate the entire class with a `path` decorator:


```python hl_lines="7 8"
from ninja import Router


router = Router()


@router.path('/project/{project_id}/tasks')
class Tasks:
    def __init__(self, request, project_id=int):
        user_projects = request.user.project_set
        self.project = get_object_or_404(user_projects, id=project_id))
        self.tasks = self.project.task_set.all()
    
    @router.get('/', response=List[TaskOut])
    def task_list(self, request):
        return self.tasks

    @router.get('/{task_id}/', response=TaskOut)
    def details(self, request, task_id: int):
        return get_object_or_404(self.tasks, id=task_id)

    @router.post('/{task_id}/complete', response=TaskOut)
    def complete(self, request, task_id: int):
        task = get_object_or_404(self.tasks, id=task_id)
        task.completed = True
        task.save()
        return task
```

All common initiation and permission checks are placed in the constructor:

```python hl_lines="4 5 6"
@router.path('/project/{project_id}/tasks')
class Tasks:
    def __init__(self, request, project_id=int):
        user_projects = request.user.project_set
        self.project = get_object_or_404(user_projects, id=project_id))
        self.tasks = self.project.task_set.all()
```

This makes the main business operation focus only on tasks (exposed as the `self.tasks` attribute)

You can use both `api` and `router` instances to support class paths.

## Issue

The `__init__` method:

```def __init__(self, request, project_id=int):```

Python doesn't support the `async` keyword for `__init__`, so to support async operations we need some other method for initialization, but `__init__` sounds the most logical.


## Your thoughts/proposals

Please give you thoughts/likes/dislikes about this proposal in the [github issue](https://github.com/vitalik/django-ninja/issues/15)


================================================
FILE: docs/docs/proposals/index.md
================================================
# Enhancement Proposals

Enhancement Proposals are a formal way of proposing large feature additions to the **Django Ninja Framework**.

You can create a proposal by making a pull request with a new page under [`docs/proposals`](https://github.com/vitalik/django-ninja/tree/master/docs/docs/proposals), or by creating an [issue on github](https://github.com/vitalik/django-ninja/issues).

Please see the current proposals:

 - [Class Based Operations](cbv.md)


================================================
FILE: docs/docs/proposals/v1.md
================================================
# Potential v1 changes

Django Ninja is already used by tens of companies and by the visitors and downloads stats it's growing.

At this point introducing changes that will force current users to change their code (or break it) is not 
acceptable.

On the other hand some decisions that where initially made does not work well. These  breaking changes will be 
introduced in version 1.0.0

## Changes that most likely be in v1

 - **auth** will be class interface instead of callable (to support async authenticators)
 - **responses** to support **codes/headers/content** (like general Response class)
 - **routers paths** currently automatically **joined with "/"** - which might not needed on some cases where router prefix will act like a prefix and not subfolder

## Your thoughts/proposals

Please give you thoughts/likes/dislikes in the [github issue](https://github.com/vitalik/django-ninja/issues/146).



================================================
FILE: docs/docs/reference/api.md
================================================
# NinjaAPI

::: ninja.main.NinjaAPI
    rendering:
      show_signature: False
      group_by_category: False


================================================
FILE: docs/docs/reference/csrf.md
================================================
# CSRF

## What is CSRF?
> [Cross Site Request Forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery) occurs when a malicious website contains a link, a form button or some JavaScript that is intended to perform some action on your website, using the credentials (or location on the network, not covered by this documentation) of a logged-in user who visits the malicious site in their browser.


## How to protect against CSRF with Django Ninja
### Use an authentication method not automatically embedded in the request
CSRF attacks rely on authentication methods that are automatically included in requests started from another site, like [cookies](https://en.wikipedia.org/wiki/HTTP_cookie) or [Basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication).
Using an authentication method that does not automatically gets embedded, such as the `Authorization: Bearer` header for exemple, mitigates this attack.


### Use Django's built-in CSRF protection
In case you are using the default Django authentication, which uses cookies, you must also use the default [Django CSRF protection](https://docs.djangoproject.com/en/4.2/ref/csrf/).


By default, **Django Ninja** has CSRF protection turned **OFF** for all operations, but will automatically enable csrf **for Cookie based** authentication:


```python hl_lines="8"
from ninja import NinjaAPI
from ninja.security import APIKeyCookie

class CookieAuth(APIKeyCookie):
    def authenticate(self, request, key):
        return key == "test"

api = NinjaAPI(auth=CookieAuth())

```


or django-auth based (which is inherited from cookie based auth):

```python hl_lines="4"
from ninja import NinjaAPI
from ninja.security import django_auth

api = NinjaAPI(auth=django_auth)
```


#### Django `ensure_csrf_cookie` decorator
You can use the Django [ensure_csrf_cookie](https://docs.djangoproject.com/en/4.2/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie) decorator on an unprotected route to make it include a `Set-Cookie` header for the CSRF token. Note that:

- The route decorator must be executed before (i.e. above) the [ensure_csrf_cookie](https://docs.djangoproject.com/en/4.2/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie) decorator).
- You must `csrf_exempt` that route.
- The `ensure_csrf_cookie` decorator works only on a Django `HttpResponse` (and subclasses like `JsonResponse`) and not on a dict like most Django Ninja decorators.
- If you [set a Cookie based authentication (which includes `django_auth`) globally to your API](../guides/authentication.md), you'll have to specifically disable auth on that route (with `auth=None` in the route decorator) as Cookie based authentication would raise an Exception when applied to an unprotected route (for security reasons).

```python hl_lines="4"
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie

@api.post("/csrf")
@ensure_csrf_cookie
@csrf_exempt
def get_csrf_token(request):
    return HttpResponse()
```
A request to that route triggers a response with the adequate `Set-Cookie` header from Django.


#### Frontend code
You may use the [Using CSRF protection with AJAX](https://docs.djangoproject.com/en/4.2/howto/csrf/#using-csrf-protection-with-ajax) and [Setting the token on the AJAX request](https://docs.djangoproject.com/en/4.2/howto/csrf/#setting-the-token-on-the-ajax-request) part of the [How to use Django’s CSRF protection](https://docs.djangoproject.com/en/4.2/howto/csrf/) to know how to handle that CSRF protection token in your frontend code.


## A word about CORS
You may want to set-up your frontend and API on different sites (in that case, you may check [django-cors-headers](https://github.com/adamchainz/django-cors-headers)).
While not directly related to CSRF, CORS (Cross-Origin Resource Sharing) may help in case you are defining the CSRF cookie on another site than the frontend consuming it, as this is not allowed by default by the [Same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy).
You may check the [django-cors-headers README](https://github.com/adamchainz/django-cors-headers#readme) then.


================================================
FILE: docs/docs/reference/management-commands.md
================================================
# Management Commands

Management commands require **Django Ninja** to be installed in Django's
`INSTALLED_APPS` setting:

```python
INSTALLED_APPS = [
    ...
    'ninja',
]
```

::: ninja.management.commands
    selection:
      filters:
        - "![A-Z]"
    rendering:
      show_root_toc_entry: False


================================================
FILE: docs/docs/reference/operations-parameters.md
================================================
# Operations parameters

## OpenAPI Schema related

The following parameters interact with how the OpenAPI schema (and docs) are generated.

### `tags`

You can group your API operations using the `tags` argument (`list[str]`). 
```python hl_lines="6"
@api.get("/hello/")
def hello(request, name: str):
    return {"hello": name}


@api.post("/orders/", tags=["orders"])
def create_order(request, order: Order):
    return {"success": True}
```

Tagged operations may be handled differently by various tools and libraries. For example, the Swagger UI uses tags to group the displayed operations.

![Summary`](../img/operation_tags.png)

#### Router tags

You can use `tags` argument to apply tags to all operations declared by router:

```python
api.add_router("/events/", events_router, tags=["events"])

# or using constructor: 

router = Router(tags=["events"])
```


### `summary`

A human-readable name for your operation.

By default, it's generated by capitalizing your operation function name:

```python hl_lines="2"
@api.get("/hello/")
def hello(request, name: str):
    return {"hello": name}
```

![Summary`](../img/operation_summary_default.png)

If you want to override it or translate it to other language, use the `summary` argument in the `api` decorator.

```python hl_lines="1"
@api.get("/hello/", summary="Say Hello")
def hello(request, name: str):
    return {"hello": name}
```

![Summary`](../img/operation_summary.png)

### `description`

To provide more information about your operation, use either the `description` argument or normal Python docstrings:


```python hl_lines="1"
@api.post("/orders/", description="Creates an order and updates stock")
def create_order(request, order: Order):
    return {"success": True}
```

![Summary`](../img/operation_description.png)

When you need to provide a long multi line description, you can use Python `docstrings` for the function definition:

```python hl_lines="4 5 6 7"
@api.post("/orders/")
def create_order(request, order: Order):
    """
    To create an order please provide:
     - **first_name**
     - **last_name**
     - and **list of Items** *(product + amount)*
    """
    return {"success": True}

```

![Summary`](../img/operation_description_docstring.png)


### `operation_id`

The OpenAPI `operationId` is an optional unique string used to identify an operation. If provided, these IDs must be unique among all operations described in your API.

By default, **Django Ninja** sets it to `module name` + `function name`.

If you want to set it individually for each operation, use the `operation_id` argument:

```python hl_lines="2"
...
@api.post("/tasks", operation_id="create_task")
def new_task(request):
    ...
```

If you want to override global behavior, you can inherit the NinjaAPI instance and override the `get_openapi_operation_id` method.

It will be called for each operation that you defined, so you can set your custom naming logic like this:

```python hl_lines="5 6 7 9"
from ninja import NinjaAPI

class MySuperApi(NinjaAPI):

    def get_openapi_operation_id(self, operation):
        # here you can access operation ( .path , .view_func, etc) 
        return ...

api = MySuperApi()

@api.get(...)
...
```

### `deprecated`

Mark an operation as deprecated without removing it by using the `deprecated` argument:

```python hl_lines="1"
@api.post("/make-order/", deprecated=True)
def some_old_method(request, order: str):
    return {"success": True}
```

It will be marked as deprecated in the JSON Schema and also in the interactive OpenAPI docs:

![Deprecated](../img/deprecated.png)

### `include_in_schema`

If you need to include/exclude some operation from OpenAPI schema use `include_in_schema` argument:

```python hl_lines="1"
@api.post("/hidden", include_in_schema=False)
def some_hidden_operation(request):
    pass
```

## openapi_extra
You can customize your OpenAPI schema for specific endpoint (detail [OpenAPI Customize Options](https://swagger.io/docs/specification/about/))
```python hl_lines="1 26"
# You can set requestBody from openapi_extra
@api.get(
    "/tasks",
    openapi_extra={
        "requestBody": {
            "content": {
                "application/json": {
                    "schema": {
                        "required": ["email"],
                        "type": "object",
                        "properties": {
                            "name": {"type": "string"},
                            "phone": {"type": "number"},
                            "email": {"type": "string"},
                        },
                    }
                }
            },
            "required": True,
        }
    },
)
def some_operation(request):
    pass
    
# You can add additional responses to the automatically generated schema
@api.post(
    "/tasks",
    openapi_extra={
        "responses": {
            400: {
                "description": "Error Response",
            },
            404: {
                "description": "Not Found Response",
            },
        },
    },
)
def some_operation_2(request):
    pass

```


## Response output options

There are a few arguments that lets you tune response's output:

### `by_alias`

Whether field aliases should be used as keys in the response (defaults to `False`).

### `exclude_unset`

Whether fields that were not set when creating the schema, and have their default values, should be excluded from the response (defaults to `False`).

### `exclude_defaults`

Whether fields which are equal to their default values (whether set or otherwise) should be excluded from the response (defaults to `False`).

### `exclude_none`

Whether fields which are equal to `None` should be excluded from the response (defaults to `False`).


## url_name
Allows you to set api endpoint url name (using [django path's naming](https://docs.djangoproject.com/en/stable/topics/http/urls/#reversing-namespaced-urls))
```python hl_lines="1 7"
@api.post("/tasks", url_name='tasks')
def some_operation(request):
    pass

# then you can get the url with

reverse('api-1.0.0:tasks')
```

See the [Reverse Resolution of URLs](../guides/urls.md) guide for more details.


## Specifying servers
If you want to specify single or multiple servers for OpenAPI specification `servers` can be used when initializing NinjaAPI instance:
```python hl_lines="4 5 6 7"
from ninja import NinjaAPI

api = NinjaAPI(
        servers=[
            {"url": "https://stag.example.com", "description": "Staging env"},
            {"url": "https://prod.example.com", "description": "Production env"},
        ]
)
```
This will allow switching between environments when using interactive OpenAPI docs:
![Servers](../img/servers.png)


================================================
FILE: docs/docs/reference/settings.md
================================================
# Django Settings

::: ninja.conf.Settings
    rendering:
      show_source: False
      show_root_toc_entry: False

================================================
FILE: docs/docs/releases.md
================================================
# Release Notes

Follow and subscribe for new releases on GitHub:

<https://github.com/vitalik/django-ninja/releases>



================================================
FILE: docs/docs/tutorial/index.md
================================================
# Tutorial - First Steps

This tutorial shows you how to use **Django Ninja** with most of its features.

This tutorial assumes that you know at least some basics of the <a href="https://www.djangoproject.com/" target="_blank">Django Framework</a>, like how to create a project and run it.

## Installation

```console
pip install django-ninja
```

!!! note

    It is not required, but you can also put `ninja` to `INSTALLED_APPS`.
    In that case the OpenAPI/Swagger UI (or Redoc) will be loaded (faster) from the included JavaScript bundle (otherwise the JavaScript bundle comes from a CDN).

## Create a Django project

Start a new Django project (or if you already have an existing Django project, skip to the next step).

```
django-admin startproject myproject
```

## Create the API

Let's create a module for our API. Create an `api.py` file in the same directory location as your Django project's root `urls.py`:

```python
from ninja import NinjaAPI

api = NinjaAPI()
```

Now go to `urls.py` and add the following:

```python hl_lines="3 7"
from django.contrib import admin
from django.urls import path
from .api import api

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/", api.urls),
]
```

## Our first operation

**Django Ninja** comes with a decorator for each HTTP method (`GET`, `POST`,
`PUT`, etc). In our `api.py` file, let's add in a simple "hello world"
operation.

```python hl_lines="5-7"
from ninja import NinjaAPI

api = NinjaAPI()

@api.get("/hello")
def hello(request):
    return "Hello world"
```

Now browsing to <a href="http://localhost:8000/api/hello"
target="_blank">localhost:8000/api/hello</a> will return a simple JSON
response:
```json
"Hello world"
```

!!! success

    Continue on to **[Parsing input](step2.md)**.

================================================
FILE: docs/docs/tutorial/other/crud.md
================================================
# CRUD example


**CRUD**  - **C**reate, **R**etrieve, **U**pdate, **D**elete are the four basic functions of persistent storage.

This example will show you how to implement these functions with **Django Ninja**.

Let's say you have the following Django models that you need to perform these operations on:


```python

class Department(models.Model):
    title = models.CharField(max_length=100)

class Employee(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    department = models.ForeignKey(Department, on_delete=models.CASCADE)
    birthdate = models.DateField(null=True, blank=True)
    cv = models.FileField(null=True, blank=True)
```

Now let's create CRUD operations for the Employee model.

## Create

To create an employee lets define an INPUT schema:

```python
from datetime import date
from ninja import Schema

class EmployeeIn(Schema):
    first_name: str
    last_name: str
    department_id: int = None
    birthdate: date = None

```

This schema will be our input payload:

```python hl_lines="2"
@api.post("/employees")
def create_employee(request, payload: EmployeeIn):
    employee = Employee.objects.create(**payload.dict())
    return {"id": employee.id}
```

!!! tip
    `Schema` objects have `.dict()` method with all the schema attributes represented as a dict.

    You can pass it as `**kwargs` to the Django model's `create` method (or model `__init__`).

See the recipe below for handling the file upload (when using Django models):

```python hl_lines="2"
from ninja import UploadedFile, File

@api.post("/employees")
def create_employee(request, payload: EmployeeIn, cv: File[UploadedFile]):
    payload_dict = payload.dict()
    employee = Employee(**payload_dict)
    employee.cv.save(cv.name, cv) # will save model instance as well
    return {"id": employee.id}
```

If you just need to handle a file upload:

```python hl_lines="2"
from django.core.files.storage import FileSystemStorage
from ninja import UploadedFile, File

STORAGE = FileSystemStorage()

@api.post("/upload")
def create_upload(request, cv: File[UploadedFile]):
    filename = STORAGE.save(cv.name, cv)
    # Handle things further
```

## Retrieve

### Single object

Now to get employee we will define a schema that will describe what our responses will look like. Here we will basically use the same schema as `EmployeeIn`, but will add an extra attribute `id`:


```python hl_lines="2"
class EmployeeOut(Schema):
    id: int
    first_name: str
    last_name: str
    department_id: int = None
    birthdate: date = None
```

!!! note
    Defining response schemas are not really required, but when you do define it you will get results validation, documentation and automatic ORM objects to JSON conversions.

We will use this schema as the `response` type for our `GET` employee view:


```python hl_lines="1"
@api.get("/employees/{employee_id}", response=EmployeeOut)
def get_employee(request, employee_id: int):
    employee = get_object_or_404(Employee, id=employee_id)
    return employee
```

Notice that we simply returned an employee ORM object, without a need to convert it to a dict. The `response` schema does automatic result validation and conversion to JSON:
```python hl_lines="4"
@api.get("/employees/{employee_id}", response=EmployeeOut)
def get_employee(request, employee_id: int):
    employee = get_object_or_404(Employee, id=employee_id)
    return employee
```

### List of objects

To output a list of employees, we can reuse the same `EmployeeOut` schema. We will just set the `response` schema to a *List* of `EmployeeOut`.
```python hl_lines="3"
from typing import List

@api.get("/employees", response=List[EmployeeOut])
def list_employees(request):
    qs = Employee.objects.all()
    return qs
```

Another cool trick - notice we just returned a Django ORM queryset:

```python hl_lines="4"
@api.get("/employees", response=List[EmployeeOut])
def list_employees(request):
    qs = Employee.objects.all()
    return qs
```
It automatically gets evaluated, validated and converted to a JSON list!



## Update

Update is pretty trivial. We just use the `PUT` method and also pass `employee_id`:

```python hl_lines="1"
@api.put("/employees/{employee_id}")
def update_employee(request, employee_id: int, payload: EmployeeIn):
    employee = get_object_or_404(Employee, id=employee_id)
    for attr, value in payload.dict().items():
        setattr(employee, attr, value)
    employee.save()
    return {"success": True}
```

**Note**

Here we used the `payload.dict` method to set all object attributes:

`for attr, value in payload.dict().items()`

You can also do this more explicit:

```python
employee.first_name = payload.first_name
employee.last_name = payload.last_name
employee.department_id = payload.department_id
employee.birthdate = payload.birthdate
```

**Partial updates**

To allow the user to make partial updates, use `payload.dict(exclude_unset=True).items()`. This ensures that only the specified fields get updated.

**Enforcing strict field validation**

By default, any provided fields that don't exist in the schema will be silently ignored. To raise an error for these invalid fields, you can set `extra = "forbid"` in the model_config. For example:

```python hl_lines="5"
from pydantic import ConfigDict
class EmployeeIn(Schema):
    # your fields here...

    model_config = ConfigDict(extra="forbid")
```

## Delete

Delete is also pretty simple. We just get employee by `id` and delete it from the DB:


```python hl_lines="1 2 4"
@api.delete("/employees/{employee_id}")
def delete_employee(request, employee_id: int):
    employee = get_object_or_404(Employee, id=employee_id)
    employee.delete()
    return {"success": True}
```

## Final code

Here's a full CRUD example:


```python
from datetime import date
from typing import List
from ninja import NinjaAPI, Schema
from django.shortcuts import get_object_or_404
from employees.models import Employee


api = NinjaAPI()


class EmployeeIn(Schema):
    first_name: str
    last_name: str
    department_id: int = None
    birthdate: date = None


class EmployeeOut(Schema):
    id: int
    first_name: str
    last_name: str
    department_id: int = None
    birthdate: date = None


@api.post("/employees")
def create_employee(request, payload: EmployeeIn):
    employee = Employee.objects.create(**payload.dict())
    return {"id": employee.id}


@api.get("/employees/{employee_id}", response=EmployeeOut)
def get_employee(request, employee_id: int):
    employee = get_object_or_404(Employee, id=employee_id)
    return employee


@api.get("/employees", response=List[EmployeeOut])
def list_employees(request):
    qs = Employee.objects.all()
    return qs


@api.put("/employees/{employee_id}")
def update_employee(request, employee_id: int, payload: EmployeeIn):
    employee = get_object_or_404(Employee, id=employee_id)
    for attr, value in payload.dict().items():
        setattr(employee, attr, value)
    employee.save()
    return {"success": True}


@api.delete("/employees/{employee_id}")
def delete_employee(request, employee_id: int):
    employee = get_object_or_404(Employee, id=employee_id)
    employee.delete()
    return {"success": True}
```


================================================
FILE: docs/docs/tutorial/other/video.md
================================================
# Video Tutorials

## Sneaky REST APIs With Django Ninja

[realpython.com/lessons/sneaky-rest-apis-with-django-ninja-overview/](https://realpython.com/lessons/sneaky-rest-apis-with-django-ninja-overview/)


## Creating a CRUD API with Django-Ninja by BugBytes (English)
<iframe width="560" height="315" src="https://www.youtube.com/embed/videoseries?list=PLXskueZ7apWgNasQPt6PYhlKNKNEghT3T" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


================================================
FILE: docs/docs/tutorial/step2.md
================================================
# Tutorial - Parsing Input

## Input from the query string

Let's change our operation to accept a name from the URL's query string. To do that, just add a `name` argument to our function.

```python
@api.get("/hello")
def hello(request, name):
    return f"Hello {name}"
```

When we provide a name argument, we get the expected (HTTP 200) response.

<a href="http://localhost:8000/api/hello?name=you"
target="_blank">localhost:8000/api/hello?name=you</a>:

```json
"Hello you"
```

### Defaults

Not providing the argument will return an HTTP 422 error response.

*[HTTP 422]: Unprocessable Entity

<a href="http://localhost:8000/api/hello"
target="_blank">localhost:8000/api/hello</a>:

```json
{
  "detail": [
    {
      "loc": ["query", "name"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
```

We can specify a default for the `name` argument in case it isn't provided:

```python hl_lines="2"
@api.get("/hello")
def hello(request, name="world"):
    return f"Hello {name}"
```

## Input types

**Django Ninja** uses standard [Python type hints](https://docs.python.org/3/library/typing.html) to format the input types. If no type is provided then a string is assumed (but it is good practice to provide type hints for all your arguments).

Let's add a second operation that does some basic math with integers.

```python hl_lines="5-7"
@api.get("/hello")
def hello(request, name: str = "world"):
    return f"Hello {name}"

@api.get("/math")
def math(request, a: int, b: int):
    return {"add": a + b, "multiply": a * b}
```

<a href="http://localhost:8000/api/math?a=2&b=3"
target="_blank">localhost:8000/api/math?a=2&b=3</a>:

```json
{
  "add": 5,
  "multiply": 6
}
```

## Input from the path

You can declare path "parameters" with the same syntax used by Python format-strings.

Any parameters found in the path string will be passed to your function as arguments, rather than expecting them from the query string.

```python hl_lines="1"
@api.get("/math/{a}and{b}")
def math(request, a: int, b: int):
    return {"add": a + b, "multiply": a * b}
```

Now we access the math operation from <a href="http://localhost:8000/api/math/2and3"
target="_blank">localhost:8000/api/math/2and3</a>.


## Input from the request body

We are going to change our `hello` operation to use HTTP `POST` instead, and take arguments from the request body.

To specify that arguments come from the body, we need to declare a Schema.

*[Schema]: An extension of a Pydantic "Model"

```python hl_lines="1 5-6 8-10"
from ninja import NinjaAPI, Schema

api = NinjaAPI()

class HelloSchema(Schema):
    name: str = "world"

@api.post("/hello")
def hello(request, data: HelloSchema):
    return f"Hello {data.name}"
```

### Self-documenting API

Accessing <a href="http://localhost:8000/api/hello" target="_blank">localhost:8000/api/hello</a> now results in a HTTP 405 error response, since we need to POST to this URL instead.

*[HTTP 405]: Method Not Allowed

An easy way to do this is to use the Swagger documentation that is automatically created for us, at default URL of "/docs" (appended to our API url root).

1. Visit <a href="http://localhost:8000/api/docs" target="_blank">localhost:8000/api/docs</a> to see the operations we have created
1. Open the `/api/hello` operation
2. Click "Try it out"
3. Change the request body
4. Click "Execute"

!!! success

    Continue on to **[Handling responses](step3.md)**

================================================
FILE: docs/docs/tutorial/step3.md
================================================
# Tutorial - Handling Responses

## Define a response Schema

**Django Ninja** allows you to define the schema of your responses both for validation and documentation purposes.

We'll create a third operation that will return information about the current Django user.

```python
from ninja import Schema

class UserSchema(Schema):
    username: str
    is_authenticated: bool
    # Unauthenticated users don't have the following fields, so provide defaults.
    email: str = None
    first_name: str = None
    last_name: str = None

@api.get("/me", response=UserSchema)
def me(request):
    return request.user
```

This will convert the Django `User` object into a dictionary of only the defined fields.

### Multiple response types

Let's return a different response if the current user is not authenticated.

```python hl_lines="2-5 7-8 10 12-13"
class UserSchema(Schema):
    username: str
    email: str
    first_name: str
    last_name: str

class Error(Schema):
    message: str

@api.get("/me", response={200: UserSchema, 403: Error})
def me(request):
    if not request.user.is_authenticated:
        return 403, {"message": "Please sign in first"}
    return request.user 
```

As you see, you can return a 2-part tuple which will be interpreted as the HTTP response code and the data.

!!! success

    That concludes the tutorial! Check out the **Other Tutorials** or the **How-to Guides** for more information.

================================================
FILE: docs/docs/whatsnew_v1.md
================================================
# Welcome to Django Ninja 1.0


To get started install latest version with
```
pip install -U django-ninja
```

django-ninja v1 is compatible with Python 3.7 and above.


Django ninja series 0.x is still supported but will receive only security updates and critical bug fixes



# What's new in Django Ninja 1.0

## Support for Pydantic2

Pydantic version 2 is re-written in Rust and includes a lot of improvements and features like:

 - Safer types.
 - Better extensibility.
 - Better performance 

By our tests average project can gain some 10% performance increase on average, while some edge parsing/serializing cases can give you 4x boost.

On the other hand it introduces breaking changes and pydantic 1 and 2 are not very compatible - but we tried or best to make this transition easy as possible. So if you used 'Schema' class migration to ninja v1 should be easy. Otherwise follow [pydantic migration guide](https://docs.pydantic.dev/latest/migration/)


Some features that are made possible with pydantic2

### pydantic context

Pydantic now supports context during validation and serialization and Django ninja passes "request" object during request and response work

```Python hl_lines="6 7"
class Payload(Schema):
    id: int
    name: str
    request_path: str

    @staticmethod
    def resolve_request_path(data, context):
        request = context["request"]
        return request.get_full_path()

```

During response a "response_code" is also passed to context

## Schema.Meta

Pydantic now deprecates BaseModel.Config class.  But to keep things consistent with all other django parts we introduce "Meta" class for ModelSchema - which works in a similar way as django's ModelForms:

```Python hl_lines="2 4"
class TxItem(ModelSchema):
    class Meta:
        model = Transaction
        fields = ["id", "account", "amount", "timestamp"]

```

(The "Config" class is still supported, but deprecated)


## Shorter / cleaner parameters syntax

```python
@api.post('/some')
def some_form(request, username: Form[str], password: Form[str]):
    return True
```

instead of

```python
@api.post('/some')
def some_form(request, username: str = Form(...), password: str = Form(...)):
    return True
```

or 

```python
@api.post('/some')
def some_form(request, data: Form[AuthSchema]):
    return True
```


instead of

```python
@api.post('/some')
def some_form(request, data: AuthSchema = Form(...)):
    return True
```



with all the autocompletion in editors


On the other hand the **old syntax is still supported** so you can easily port your project to a newer django-ninja version without much haste 


#### + Annotated

typing.Annotated is also supported:

```Python
@api.get("/annotated")
def annotated(request, data: Annotated[SomeData, Form()]):
    return {"data": data.dict()}

```


## Async auth support

The async authenticators are finally supported. All you have to do is just add `async` to your `authenticate` method:

```Python
class Auth(HttpBearer):
    async def authenticate(self, request, token):
        await asyncio.sleep(1)
        if token == "secret":
            return token

```


## Changed CSRF Behavior


`csrf=True` requirement is no longer required if you use cookie based authentication. Instead CSRF protection is enabled automatically. This also allow you to  mix csrf-protected authenticators and other methods that does not require cookies:

```Python
api = NinjaAPI(auth=[django_auth, Auth()])
```


## Docs

Doc viewer are now configurable and plugable. By default django ninja comes with Swagger and Redoc:

```Python
from ninja import NinjaAPI, Redoc, Swagger


# use redoc
api = NinjaAPI(docs=Redoc()))

# use swagger:
api = NinjaAPI(docs=Swagger())

# set configuration for swagger:
api = NinjaAPI(docs=Swagger({"persistAuthorization": True}))
```

Users now able to create custom docs viewer by inheriting `DocsBase` class

## Router

add_router supports string paths:

```Python
api = NinjaAPI()


api.add_router('/app1', 'myproject.app1.router')
api.add_router('/app2', 'myproject.app2.router')
api.add_router('/app3', 'myproject.app3.router')
api.add_router('/app4', 'myproject.app4.router')
api.add_router('/app5', 'myproject.app5.router')
```


## Decorators

When django ninja decorates a view with .get/.post etc. - it wraps the result of the function (which in most cases are not HttpResponse - but some serializable object) so it's not really possible to use some built-in or 3rd-party decorators like:

```python hl_lines="4"
from django.views.decorators.cache import cache_page

@api.get("/test")
@cache_page(5) # <----- will not work
def test_view(request):
    return {"some": "Complex data"}
```
This example does not work.

Now django ninja introduces a decorator decorate_view that allows inject decorators that work with http response:

```python hl_lines="1 4"
from ninja.decorators import decorate_view

@api.get("/test")
@decorate_view(cache_page(5))
def test_view(request):
    return str(datetime.now())
```


## Paginations

`paginate_queryset` method now takes `request` object


#### Backwards incompatible stuff
 - resolve_xxx(self, ...) - support resolve with (self) is dropped in favor of pydantic build-in functionality
 - pydantic v1 is no longer supported
 - python 3.6 is no longer supported

BTW - if you like this project and still did not give it a github start - please do so ![github star](img/github-star.png)


================================================
FILE: docs/mkdocs.yml
================================================
site_name: Django Ninja
site_description: Django Ninja - Django REST framework with high performance, easy to learn, fast to code.
site_url: https://django-ninja.dev
repo_name: vitalik/django-ninja
repo_url: https://github.com/vitalik/django-ninja
edit_uri: ""
extra:
  analytics:
    provider: google
    property: G-0E3XZ663ZR
extra_css:
  - extra.css
extra_javascript:
  - javascripts/ask-ai-button.js
theme:
  name: material
  palette:
    - media: "(prefers-color-scheme)"
      primary: green
      toggle:
        icon: material/brightness-auto
        name: Switch to light mode
    - media: "(prefers-color-scheme: light)"
      scheme: default
      primary: green
      toggle:
        icon: material/weather-night
        name: Switch to dark mode
    - media: "(prefers-color-scheme: dark)" 
      scheme: slate
      primary: green
      toggle:
        icon: material/weather-sunny
        name: Switch to light mode
  logo: img/docs-logo.png
  favicon: img/favicon.svg
  language: en
  features:
    - navigation.expand
    - search.highlight
    - search.suggest
  icon:
    repo: fontawesome/brands/github-alt
nav:
  - Intro: index.md
  - motivation.md
  - Tutorial:
      - "First Steps": tutorial/index.md
      - "Parsing Input": tutorial/step2.md
      - "Handling Responses": tutorial/step3.md
      - Other Tutorials:
          - tutorial/other/video.md
          - tutorial/other/crud.md
  - How-to Guides:
      - Parsing input:
          - guides/input/operations.md
          - guides/input/path-params.md
          - guides/input/query-params.md
          - guides/input/body.md
          - guides/input/form-params.md
          - guides/input/file-params.md
          - guides/input/request-parsers.md
          - guides/input/filtering.md
      - Handling responses:
          - Defining a Schema: guides/response/index.md
          - guides/response/temporal_response.md
          - Generating a Schema from Django models: guides/response/django-pydantic.md
          - Generating a Schema dynamically: guides/response/django-pydantic-create-schema.md
          - guides/response/config-pydantic.md
          - guides/response/pagination.md
          - guides/response/response-renderers.md
      - Splitting your API with Routers: guides/routers.md
      - guides/decorators.md
      - guides/authentication.md
      - guides/throttling.md
      - guides/testing.md
      - guides/api-docs.md
      - guides/errors.md
      - guides/urls.md
      - guides/async-support.md
      - guides/versioning.md
  - Reference:
      - NinjaAPI class: reference/api.md
      - reference/csrf.md
      - reference/operations-parameters.md
      - reference/management-commands.md
      - reference/settings.md
      - releases.md
  - help.md
  - Enhancement Proposals:
      - Intro: proposals/index.md
      - proposals/cbv.md
      - proposals/v1.md
  - What's new in V1: whatsnew_v1.md
markdown_extensions:
  - markdown_include.include
  - markdown.extensions.codehilite:
      guess_lang: false
  # Uncomment these 2 lines during development to more easily add highlights
  #- pymdownx.highlight:
  #    linenums: true
  - abbr
  - codehilite
  - admonition
  - pymdownx.details
  - pymdownx.superfences
plugins:
  - search
  - mkdocstrings:
      handlers:
        python:
          setup_commands:
            - from django.conf import settings
            - settings.configure()


================================================
FILE: docs/requirements.txt
================================================
mkdocs==1.5.3
mkdocs-autorefs==1.0.1
mkdocs-material==9.5.4
mkdocs-material-extensions==1.3.1
markdown-include==0.8.1
mkdocstrings[python]==0.24.0
griffe==0.47.0


================================================
FILE: docs/src/index001.py
================================================
from django.contrib import admin
from django.urls import path
from ninja import NinjaAPI

api = NinjaAPI()


@api.get("/add")
def add(request, a: int, b: int):
    return {"result": a + b}


urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/", api.urls),
]


================================================
FILE: docs/src/tutorial/authentication/apikey01.py
================================================
from ninja.security import APIKeyQuery
from someapp.models import Client


class ApiKey(APIKeyQuery):
    param_name = "api_key"

    def authenticate(self, request, key):
        try:
            return Client.objects.get(key=key)
        except Client.DoesNotExist:
            pass


api_key = ApiKey()


@api.get("/apikey", auth=api_key)
def apikey(request):
    assert isinstance(request.auth, Client)
    return f"Hello {request.auth}"


================================================
FILE: docs/src/tutorial/authentication/apikey02.py
================================================
from ninja.security import APIKeyHeader


class ApiKey(APIKeyHeader):
    param_name = "X-API-Key"

    def authenticate(self, request, key):
        if key == "supersecret":
            return key


header_key = ApiKey()


@api.get("/headerkey", auth=header_key)
def apikey(request):
    return f"Token = {request.auth}"


================================================
FILE: docs/src/tutorial/authentication/apikey03.py
================================================
from ninja.security import APIKeyCookie


class CookieKey(APIKeyCookie):
    def authenticate(self, request, key):
        if key == "supersecret":
            return key


cookie_key = CookieKey()


@api.get("/cookiekey", auth=cookie_key)
def apikey(request):
    return f"Token = {request.auth}"


================================================
FILE: docs/src/tutorial/authentication/basic01.py
================================================
from ninja.security import HttpBasicAuth


class BasicAuth(HttpBasicAuth):
    def authenticate(self, request, username, password):
        if username == "admin" and password == "secret":
            return username


@api.get("/basic", auth=BasicAuth())
def basic(request):
    return {"httpuser": request.auth}


================================================
FILE: docs/src/tutorial/authentication/bearer01.py
================================================
from ninja.security import HttpBearer


class AuthBearer(HttpBearer):
    def authenticate(self, request, token):
        if token == "supersecret":
            return token


@api.get("/bearer", auth=AuthBearer())
def bearer(request):
    return {"token": request.auth}


================================================
FILE: docs/src/tutorial/authentication/bearer02.py
================================================
from ninja import NinjaAPI
from ninja.security import HttpBearer

api = NinjaAPI()

class InvalidToken(Exception):
    pass

@api.exception_handler(InvalidToken)
def on_invalid_token(request, exc):
    return api.create_response(request, {"detail": "Invalid token supplied"}, status=401)

class AuthBearer(HttpBearer):
    def authenticate(self, request, token):
        if token == "supersecret":
            return token
        raise InvalidToken


@api.get("/bearer", auth=AuthBearer())
def bearer(request):
    return {"token": request.auth}


================================================
FILE: docs/src/tutorial/authentication/code001.py
================================================
from ninja import NinjaAPI
from ninja.security import django_auth

api = NinjaAPI()


@api.get("/pets", auth=django_auth)
def pets(request):
    return f"Authenticated user {request.auth}"


================================================
FILE: docs/src/tutorial/authentication/code002.py
================================================
def ip_whitelist(request):
    if request.META["REMOTE_ADDR"] == "8.8.8.8":
        return "8.8.8.8"


@api.get("/ipwhitelist", auth=ip_whitelist)
def ipwhitelist(request):
    return f"Authenticated client, IP = {request.auth}"


================================================
FILE: docs/src/tutorial/authentication/global01.py
================================================
from ninja import NinjaAPI, Form
from ninja.security import HttpBearer


class GlobalAuth(HttpBearer):
    def authenticate(self, request, token):
        if token == "supersecret":
            return token


api = NinjaAPI(auth=GlobalAuth())

# @api.get(...)
# def ...
# @api.post(...)
# def ...


@api.post("/token", auth=None)  # < overriding global auth
def get_token(request, username: str = Form(...), password: str = Form(...)):
    if username == "admin" and password == "giraffethinnknslong":
        return {"token": "supersecret"}


================================================
FILE: docs/src/tutorial/authentication/multiple01.py
================================================
from ninja.security import APIKeyQuery, APIKeyHeader


class AuthCheck:
    def authenticate(self, request, key):
        if key == "supe
Download .txt
gitextract_4zhr2mua/

├── .dockerignore
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── feature_request.md
│   │   └── question.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── close-old-issues.yml
│       ├── docs.yml
│       ├── publish.yml
│       ├── test.yml
│       └── test_full.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── docs/
│   ├── docs/
│   │   ├── chat.md
│   │   ├── extra.css
│   │   ├── guides/
│   │   │   ├── api-docs.md
│   │   │   ├── async-support.md
│   │   │   ├── authentication.md
│   │   │   ├── decorators.md
│   │   │   ├── errors.md
│   │   │   ├── input/
│   │   │   │   ├── body.md
│   │   │   │   ├── file-params.md
│   │   │   │   ├── filtering.md
│   │   │   │   ├── form-params.md
│   │   │   │   ├── operations.md
│   │   │   │   ├── path-params.md
│   │   │   │   ├── query-params.md
│   │   │   │   └── request-parsers.md
│   │   │   ├── response/
│   │   │   │   ├── config-pydantic.md
│   │   │   │   ├── django-pydantic-create-schema.md
│   │   │   │   ├── django-pydantic.md
│   │   │   │   ├── index.md
│   │   │   │   ├── pagination.md
│   │   │   │   ├── response-renderers.md
│   │   │   │   └── temporal_response.md
│   │   │   ├── routers.md
│   │   │   ├── testing.md
│   │   │   ├── throttling.md
│   │   │   ├── urls.md
│   │   │   └── versioning.md
│   │   ├── help.md
│   │   ├── index.md
│   │   ├── javascripts/
│   │   │   └── ask-ai-button.js
│   │   ├── motivation.md
│   │   ├── proposals/
│   │   │   ├── cbv.md
│   │   │   ├── index.md
│   │   │   └── v1.md
│   │   ├── reference/
│   │   │   ├── api.md
│   │   │   ├── csrf.md
│   │   │   ├── management-commands.md
│   │   │   ├── operations-parameters.md
│   │   │   └── settings.md
│   │   ├── releases.md
│   │   ├── tutorial/
│   │   │   ├── index.md
│   │   │   ├── other/
│   │   │   │   ├── crud.md
│   │   │   │   └── video.md
│   │   │   ├── step2.md
│   │   │   └── step3.md
│   │   └── whatsnew_v1.md
│   ├── mkdocs.yml
│   ├── requirements.txt
│   └── src/
│       ├── index001.py
│       └── tutorial/
│           ├── authentication/
│           │   ├── apikey01.py
│           │   ├── apikey02.py
│           │   ├── apikey03.py
│           │   ├── basic01.py
│           │   ├── bearer01.py
│           │   ├── bearer02.py
│           │   ├── code001.py
│           │   ├── code002.py
│           │   ├── global01.py
│           │   ├── multiple01.py
│           │   └── schema01.py
│           ├── body/
│           │   ├── code01.py
│           │   ├── code02.py
│           │   └── code03.py
│           ├── form/
│           │   ├── code01.py
│           │   ├── code02.py
│           │   └── code03.py
│           ├── path/
│           │   ├── code01.py
│           │   ├── code010.py
│           │   └── code02.py
│           └── query/
│               ├── code01.py
│               ├── code010.py
│               ├── code02.py
│               └── code03.py
├── mypy.ini
├── ninja/
│   ├── __init__.py
│   ├── compatibility/
│   │   ├── __init__.py
│   │   ├── files.py
│   │   ├── streaming.py
│   │   └── util.py
│   ├── conf.py
│   ├── constants.py
│   ├── decorators.py
│   ├── errors.py
│   ├── files.py
│   ├── filter_schema.py
│   ├── main.py
│   ├── management/
│   │   ├── __init__.py
│   │   ├── commands/
│   │   │   ├── __init__.py
│   │   │   └── export_openapi_schema.py
│   │   └── utils.py
│   ├── openapi/
│   │   ├── __init__.py
│   │   ├── docs.py
│   │   ├── schema.py
│   │   ├── urls.py
│   │   └── views.py
│   ├── operation.py
│   ├── orm/
│   │   ├── __init__.py
│   │   ├── factory.py
│   │   ├── fields.py
│   │   ├── metaclass.py
│   │   └── shortcuts.py
│   ├── pagination.py
│   ├── params/
│   │   ├── __init__.py
│   │   ├── functions.py
│   │   └── models.py
│   ├── parser.py
│   ├── patch_dict.py
│   ├── py.typed
│   ├── renderers.py
│   ├── responses.py
│   ├── router.py
│   ├── schema.py
│   ├── security/
│   │   ├── __init__.py
│   │   ├── apikey.py
│   │   ├── base.py
│   │   ├── http.py
│   │   └── session.py
│   ├── signature/
│   │   ├── __init__.py
│   │   ├── details.py
│   │   └── utils.py
│   ├── static/
│   │   └── ninja/
│   │       ├── redoc.standalone.js
│   │       ├── swagger-ui-bundle.js
│   │       ├── swagger-ui-init.js
│   │       └── swagger-ui.css
│   ├── streaming.py
│   ├── templates/
│   │   └── ninja/
│   │       ├── favicons.html
│   │       ├── redoc.html
│   │       ├── redoc_cdn.html
│   │       ├── swagger.html
│   │       └── swagger_cdn.html
│   ├── testing/
│   │   ├── __init__.py
│   │   └── client.py
│   ├── throttling.py
│   ├── types.py
│   └── utils.py
├── pyproject.toml
├── scripts/
│   └── build-docs.sh
└── tests/
    ├── conftest.py
    ├── demo_project/
    │   ├── db.sqlite3
    │   ├── demo/
    │   │   ├── __init__.py
    │   │   ├── asgi.py
    │   │   ├── settings.py
    │   │   ├── urls.py
    │   │   └── wsgi.py
    │   ├── manage.py
    │   ├── multi_param/
    │   │   ├── __init__.py
    │   │   ├── api.py
    │   │   ├── asgi.py
    │   │   ├── manage.py
    │   │   ├── settings.py
    │   │   ├── urls.py
    │   │   └── wsgi.py
    │   └── someapp/
    │       ├── __init__.py
    │       ├── admin.py
    │       ├── api.py
    │       ├── models.py
    │       └── views.py
    ├── env-matrix/
    │   ├── Dockerfile
    │   ├── Dockerfile.backup
    │   ├── README.md
    │   ├── create_docker.py
    │   ├── docker-compose.yml
    │   ├── install_env.sh
    │   └── run.sh
    ├── main.py
    ├── mypy_test.py
    ├── pytest.ini
    ├── test_add_decorator.py
    ├── test_add_decorator_async.py
    ├── test_alias.py
    ├── test_annotated.py
    ├── test_api_instance.py
    ├── test_app.py
    ├── test_async.py
    ├── test_auth.py
    ├── test_auth_async.py
    ├── test_auth_global.py
    ├── test_auth_inheritance_routers.py
    ├── test_auth_routers.py
    ├── test_body.py
    ├── test_compatibility.py
    ├── test_conf.py
    ├── test_csrf.py
    ├── test_csrf_async.py
    ├── test_decorators.py
    ├── test_discriminator.py
    ├── test_django_models.py
    ├── test_docs/
    │   ├── __init__.py
    │   ├── test_auth.py
    │   ├── test_body.py
    │   ├── test_form.py
    │   ├── test_index.py
    │   ├── test_path.py
    │   └── test_query.py
    ├── test_enum.py
    ├── test_errors.py
    ├── test_exceptions.py
    ├── test_export_openapi_schema.py
    ├── test_files.py
    ├── test_filter_schema.py
    ├── test_forms.py
    ├── test_forms_and_files.py
    ├── test_inheritance_routers.py
    ├── test_lists.py
    ├── test_misc.py
    ├── test_models.py
    ├── test_openapi_docs.py
    ├── test_openapi_extra.py
    ├── test_openapi_params.py
    ├── test_openapi_schema.py
    ├── test_orm_metaclass.py
    ├── test_orm_relations.py
    ├── test_orm_schemas.py
    ├── test_pagination.py
    ├── test_pagination_async.py
    ├── test_pagination_cursor.py
    ├── test_pagination_router.py
    ├── test_params_models.py
    ├── test_parser.py
    ├── test_patch_dict.py
    ├── test_path.py
    ├── test_pydantic_migrate.py
    ├── test_query.py
    ├── test_query_schema.py
    ├── test_renderer.py
    ├── test_request.py
    ├── test_response.py
    ├── test_response_cookies.py
    ├── test_response_multiple.py
    ├── test_response_params.py
    ├── test_reverse.py
    ├── test_router_add_router.py
    ├── test_router_defaults.py
    ├── test_router_path_params.py
    ├── test_router_reuse.py
    ├── test_schema.py
    ├── test_schema_context.py
    ├── test_serialization_context.py
    ├── test_server.py
    ├── test_signature_details.py
    ├── test_status.py
    ├── test_streaming.py
    ├── test_test_client.py
    ├── test_throttling.py
    ├── test_union.py
    ├── test_utils.py
    ├── test_with_django/
    │   ├── __init__.py
    │   ├── schema_fixtures/
    │   │   ├── test-multi-body-file.json
    │   │   ├── test-multi-body-form-file.json
    │   │   ├── test-multi-body-form.json
    │   │   ├── test-multi-body.json
    │   │   ├── test-multi-cookie.json
    │   │   ├── test-multi-form-body-file.json
    │   │   ├── test-multi-form-body.json
    │   │   ├── test-multi-form-file.json
    │   │   ├── test-multi-form.json
    │   │   ├── test-multi-header.json
    │   │   ├── test-multi-path.json
    │   │   └── test-multi-query.json
    │   └── test_multi_param_parsing.py
    ├── test_wraps.py
    └── util.py
Download .txt
Showing preview only (646K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (6169 symbols across 157 files)

FILE: docs/src/index001.py
  function add (line 9) | def add(request, a: int, b: int):

FILE: docs/src/tutorial/authentication/apikey01.py
  class ApiKey (line 5) | class ApiKey(APIKeyQuery):
    method authenticate (line 8) | def authenticate(self, request, key):
  function apikey (line 19) | def apikey(request):

FILE: docs/src/tutorial/authentication/apikey02.py
  class ApiKey (line 4) | class ApiKey(APIKeyHeader):
    method authenticate (line 7) | def authenticate(self, request, key):
  function apikey (line 16) | def apikey(request):

FILE: docs/src/tutorial/authentication/apikey03.py
  class CookieKey (line 4) | class CookieKey(APIKeyCookie):
    method authenticate (line 5) | def authenticate(self, request, key):
  function apikey (line 14) | def apikey(request):

FILE: docs/src/tutorial/authentication/basic01.py
  class BasicAuth (line 4) | class BasicAuth(HttpBasicAuth):
    method authenticate (line 5) | def authenticate(self, request, username, password):
  function basic (line 11) | def basic(request):

FILE: docs/src/tutorial/authentication/bearer01.py
  class AuthBearer (line 4) | class AuthBearer(HttpBearer):
    method authenticate (line 5) | def authenticate(self, request, token):
  function bearer (line 11) | def bearer(request):

FILE: docs/src/tutorial/authentication/bearer02.py
  class InvalidToken (line 6) | class InvalidToken(Exception):
  function on_invalid_token (line 10) | def on_invalid_token(request, exc):
  class AuthBearer (line 13) | class AuthBearer(HttpBearer):
    method authenticate (line 14) | def authenticate(self, request, token):
  function bearer (line 21) | def bearer(request):

FILE: docs/src/tutorial/authentication/code001.py
  function pets (line 8) | def pets(request):

FILE: docs/src/tutorial/authentication/code002.py
  function ip_whitelist (line 1) | def ip_whitelist(request):
  function ipwhitelist (line 7) | def ipwhitelist(request):

FILE: docs/src/tutorial/authentication/global01.py
  class GlobalAuth (line 5) | class GlobalAuth(HttpBearer):
    method authenticate (line 6) | def authenticate(self, request, token):
  function get_token (line 20) | def get_token(request, username: str = Form(...), password: str = Form(....

FILE: docs/src/tutorial/authentication/multiple01.py
  class AuthCheck (line 4) | class AuthCheck:
    method authenticate (line 5) | def authenticate(self, request, key):
  class QueryKey (line 10) | class QueryKey(AuthCheck, APIKeyQuery):
  class HeaderKey (line 14) | class HeaderKey(AuthCheck, APIKeyHeader):
  function multiple (line 19) | def multiple(request):

FILE: docs/src/tutorial/body/code01.py
  class Item (line 5) | class Item(Schema):
  function create (line 13) | def create(request, item: Item):

FILE: docs/src/tutorial/body/code02.py
  class Item (line 4) | class Item(Schema):
  function update (line 12) | def update(request, item_id: int, item: Item):

FILE: docs/src/tutorial/body/code03.py
  class Item (line 4) | class Item(Schema):
  function update (line 12) | def update(request, item_id: int, item: Item, q: str):

FILE: docs/src/tutorial/form/code01.py
  class Item (line 4) | class Item(Schema):
  function create (line 12) | def create(request, item: Form[Item]):

FILE: docs/src/tutorial/form/code02.py
  class Item (line 4) | class Item(Schema):
  function update (line 12) | def update(request, item_id: int, q: str, item: Form[Item]):

FILE: docs/src/tutorial/form/code03.py
  function _empty_str_to_default (line 7) | def _empty_str_to_default(v, handler, info):
  class Item (line 17) | class Item(Schema):
  function update (line 26) | def update(request, item: Form[Item]):

FILE: docs/src/tutorial/path/code01.py
  function read_item (line 2) | def read_item(request, item_id):

FILE: docs/src/tutorial/path/code010.py
  class PathDate (line 5) | class PathDate(Schema):
    method value (line 10) | def value(self):
  function events (line 15) | def events(request, date: Path[PathDate]):

FILE: docs/src/tutorial/path/code02.py
  function read_item (line 2) | def read_item(request, item_id: int):

FILE: docs/src/tutorial/query/code01.py
  function list_weapons (line 5) | def list_weapons(request, limit: int = 10, offset: int = 0):

FILE: docs/src/tutorial/query/code010.py
  class Filters (line 9) | class Filters(Schema):
  function events (line 17) | def events(request, filters: Query[Filters]):

FILE: docs/src/tutorial/query/code02.py
  function search_weapons (line 5) | def search_weapons(request, q: str, offset: int = 0):

FILE: docs/src/tutorial/query/code03.py
  function example (line 5) | def example(request, s: str = None, b: bool = None, d: date = None, i: i...

FILE: ninja/compatibility/files.py
  function need_to_fix_request_files (line 15) | def need_to_fix_request_files(methods: List[str], params_models: List[An...
  function fix_request_files_middleware (line 25) | def fix_request_files_middleware(get_response: Any) -> Any:

FILE: ninja/compatibility/streaming.py
  function _copy_temporal_headers (line 34) | def _copy_temporal_headers(
  function create_streaming_response (line 47) | async def create_streaming_response(
  function create_streaming_response (line 77) | async def create_streaming_response(

FILE: ninja/compatibility/util.py
  function get_annotations_from_namespace (line 22) | def get_annotations_from_namespace(namespace: dict) -> dict:
  function get_annotations_from_namespace (line 32) | def get_annotations_from_namespace(namespace: dict) -> dict:

FILE: ninja/conf.py
  class Settings (line 8) | class Settings(BaseModel):

FILE: ninja/constants.py
  class NOT_SET_TYPE (line 6) | class NOT_SET_TYPE:
    method __repr__ (line 7) | def __repr__(self) -> str:  # pragma: no cover
    method __copy__ (line 10) | def __copy__(self) -> Any:
    method __deepcopy__ (line 13) | def __deepcopy__(self, memodict: Optional[Dict] = None) -> Any:

FILE: ninja/decorators.py
  function decorate_view (line 27) | def decorate_view(*decorators: Callable[..., Any]) -> Callable[[TCallabl...
  function _apply_decorators (line 43) | def _apply_decorators(

FILE: ninja/errors.py
  class ConfigError (line 29) | class ConfigError(Exception):
  class ValidationErrorContext (line 36) | class ValidationErrorContext(Generic[TModel]):
    method __init__ (line 42) | def __init__(
  class ValidationError (line 49) | class ValidationError(Exception):
    method __init__ (line 56) | def __init__(self, errors: List[DictStrAny]) -> None:
  class HttpError (line 61) | class HttpError(Exception):
    method __init__ (line 62) | def __init__(self, status_code: int, message: str) -> None:
    method __str__ (line 67) | def __str__(self) -> str:
  class AuthenticationError (line 71) | class AuthenticationError(HttpError):
    method __init__ (line 72) | def __init__(self, status_code: int = 401, message: str = "Unauthorize...
  class AuthorizationError (line 76) | class AuthorizationError(HttpError):
    method __init__ (line 77) | def __init__(self, status_code: int = 403, message: str = "Forbidden")...
  class Throttled (line 81) | class Throttled(HttpError):
    method __init__ (line 82) | def __init__(self, wait: Optional[int]) -> None:
  function set_default_exc_handlers (line 87) | def set_default_exc_handlers(api: "NinjaAPI") -> None:
  function _default_404 (line 106) | def _default_404(request: HttpRequest, exc: Exception, api: "NinjaAPI") ...
  function _default_http_error (line 113) | def _default_http_error(
  function _default_validation_error (line 119) | def _default_validation_error(
  function _default_exception (line 125) | def _default_exception(

FILE: ninja/files.py
  class UploadedFile (line 9) | class UploadedFile(DjangoUploadedFile):
    method __get_pydantic_json_schema__ (line 11) | def __get_pydantic_json_schema__(
    method _validate (line 20) | def _validate(cls, v: Any, _: Any) -> Any:
    method __get_pydantic_core_schema__ (line 26) | def __get_pydantic_core_schema__(

FILE: ninja/filter_schema.py
  class FilterLookup (line 21) | class FilterLookup:
    method __init__ (line 31) | def __init__(
  class FilterConfigDict (line 55) | class FilterConfigDict(ConfigDict, total=False):
  class FilterSchema (line 60) | class FilterSchema(Schema):
    method custom_expression (line 66) | def custom_expression(self) -> Q:
    method get_filter_expression (line 72) | def get_filter_expression(self) -> Q:
    method filter (line 81) | def filter(self, queryset: T) -> T:
    method _get_filter_lookup (line 84) | def _get_filter_lookup(
    method _get_field_q_expression (line 108) | def _get_field_q_expression(
    method _get_field_expression_connector (line 123) | def _get_field_expression_connector(
    method _get_field_ignore_none (line 140) | def _get_field_ignore_none(
    method _resolve_field_expression (line 155) | def _resolve_field_expression(
    method _connect_fields (line 193) | def _connect_fields(self) -> Q:
    method _get_from_deprecated_field_extra (line 225) | def _get_from_deprecated_field_extra(

FILE: ninja/main.py
  class NinjaAPI (line 47) | class NinjaAPI:
    method __init__ (line 52) | def __init__(
    method get (line 123) | def get(
    method post (line 166) | def post(
    method delete (line 209) | def delete(
    method patch (line 252) | def patch(
    method put (line 295) | def put(
    method api_operation (line 338) | def api_operation(
    method add_decorator (line 379) | def add_decorator(
    method add_router (line 395) | def add_router(
    method urls (line 452) | def urls(self) -> Tuple[List[Union[URLResolver, URLPattern]], str, str]:
    method _get_bound_routers (line 468) | def _get_bound_routers(self) -> List[BoundRouter]:
    method _get_urls (line 530) | def _get_urls(self) -> List[Union[URLResolver, URLPattern]]:
    method get_root_path (line 539) | def get_root_path(self, path_params: DictStrAny) -> str:
    method create_response (line 543) | def create_response(
    method create_temporal_response (line 567) | def create_temporal_response(self, request: HttpRequest) -> HttpResponse:
    method get_content_type (line 570) | def get_content_type(self) -> str:
    method get_openapi_schema (line 573) | def get_openapi_schema(
    method get_openapi_operation_id (line 583) | def get_openapi_operation_id(self, operation: "Operation") -> str:
    method get_operation_url_name (line 588) | def get_operation_url_name(self, operation: "Operation", router: Route...
    method add_exception_handler (line 595) | def add_exception_handler(
    method exception_handler (line 601) | def exception_handler(
    method set_default_exception_handlers (line 610) | def set_default_exception_handlers(self) -> None:
    method on_exception (line 613) | def on_exception(self, request: HttpRequest, exc: Exc[_E]) -> HttpResp...
    method validation_error_from_error_contexts (line 619) | def validation_error_from_error_contexts(
    method _lookup_exception_handler (line 641) | def _lookup_exception_handler(self, exc: Exc[_E]) -> Optional[ExcHandl...
    method _validate (line 648) | def _validate(self) -> None:

FILE: ninja/management/commands/export_openapi_schema.py
  class Command (line 14) | class Command(BaseCommand):
    method _get_api_instance (line 29) | def _get_api_instance(self, api_path: Optional[str] = None) -> NinjaAPI:
    method add_arguments (line 50) | def add_arguments(self, parser: CommandParser) -> None:
    method handle (line 83) | def handle(self, *args: Any, **options: Any) -> None:

FILE: ninja/management/utils.py
  function command_docstring (line 7) | def command_docstring(cmd: Type[BaseCommand]) -> str:

FILE: ninja/openapi/docs.py
  class DocsBase (line 21) | class DocsBase(ABC):
    method render_page (line 23) | def render_page(
    method get_openapi_url (line 28) | def get_openapi_url(self, api: "NinjaAPI", path_params: DictStrAny) ->...
  class Swagger (line 32) | class Swagger(DocsBase):
    method __init__ (line 40) | def __init__(self, settings: Optional[DictStrAny] = None):
    method render_page (line 46) | def render_page(
  class Redoc (line 58) | class Redoc(DocsBase):
    method __init__ (line 63) | def __init__(self, settings: Optional[DictStrAny] = None):
    method render_page (line 69) | def render_page(
  function render_template (line 80) | def render_template(
  function _render_cdn_template (line 94) | def _render_cdn_template(
  function _csrf_needed (line 105) | def _csrf_needed(api: "NinjaAPI") -> bool:

FILE: ninja/openapi/schema.py
  function get_schema (line 28) | def get_schema(api: "NinjaAPI", path_prefix: str = "") -> "OpenAPISchema":
  class OpenAPISchema (line 36) | class OpenAPISchema(dict):
    method __init__ (line 37) | def __init__(self, api: "NinjaAPI", path_prefix: str) -> None:
    method get_paths (line 63) | def get_paths(self) -> DictStrAny:
    method methods (line 83) | def methods(self, operations: list) -> DictStrAny:
    method deep_dict_update (line 92) | def deep_dict_update(
    method operation_details (line 113) | def operation_details(self, operation: Operation) -> DictStrAny:
    method operation_parameters (line 151) | def operation_parameters(self, operation: Operation) -> List[DictStrAny]:
    method _extract_parameters (line 158) | def _extract_parameters(self, model: TModel) -> List[DictStrAny]:
    method _flatten_schema (line 204) | def _flatten_schema(self, model: TModel) -> DictStrAny:
    method _create_schema_from_model (line 216) | def _create_schema_from_model(
    method _create_multipart_schema_from_models (line 246) | def _create_multipart_schema_from_models(
    method request_body (line 263) | def request_body(self, operation: Operation) -> DictStrAny:
    method responses (line 291) | def responses(self, operation: Operation) -> Dict[int, DictStrAny]:
    method operation_security (line 318) | def operation_security(self, operation: Operation) -> Optional[List[Di...
    method get_components (line 330) | def get_components(self) -> DictStrAny:
    method add_schema_definitions (line 336) | def add_schema_definitions(self, definitions: dict) -> None:
  function flatten_properties (line 345) | def flatten_properties(
  function resolve_allOf (line 385) | def resolve_allOf(details: DictStrAny, definitions: DictStrAny) -> None:
  function merge_schemas (line 396) | def merge_schemas(schemas: List[DictStrAny]) -> DictStrAny:

FILE: ninja/openapi/urls.py
  function get_openapi_urls (line 14) | def get_openapi_urls(api: "NinjaAPI") -> List[Any]:
  function get_root_url (line 40) | def get_root_url(api: "NinjaAPI") -> Any:

FILE: ninja/openapi/views.py
  function default_home (line 13) | def default_home(request: HttpRequest, api: "NinjaAPI", **kwargs: Any) -...
  function openapi_json (line 19) | def openapi_json(request: HttpRequest, api: "NinjaAPI", **kwargs: Any) -...
  function openapi_view (line 24) | def openapi_view(request: HttpRequest, api: "NinjaAPI", **kwargs: Any) -...

FILE: ninja/operation.py
  class Operation (line 53) | class Operation:
    method __init__ (line 54) | def __init__(
    method clone (line 143) | def clone(self) -> "Operation":
    method run (line 209) | def run(self, request: HttpRequest, **kw: Any) -> HttpResponseBase:
    method _validate_stream_item (line 227) | def _validate_stream_item(self, item: Any, request: HttpRequest) -> str:
    method _stream_response (line 251) | def _stream_response(
    method _set_auth (line 282) | def _set_auth(
    method _run_checks (line 288) | def _run_checks(self, request: HttpRequest) -> Optional[HttpResponse]:
    method _run_authentication (line 311) | def _run_authentication(self, request: HttpRequest) -> Optional[HttpRe...
    method _check_throttles (line 328) | def _check_throttles(self, request: HttpRequest) -> Optional[HttpRespo...
    method _model_dump_kwargs (line 344) | def _model_dump_kwargs(self, request: HttpRequest, status: int) -> Dic...
    method _result_to_response (line 350) | def _result_to_response(
    method _get_values (line 437) | def _get_values(
    method _create_response_model_multiple (line 459) | def _create_response_model_multiple(
    method _create_response_model (line 469) | def _create_response_model(self, response_param: Any) -> Optional[Type...
  class AsyncOperation (line 476) | class AsyncOperation(Operation):
    method __init__ (line 477) | def __init__(self, *args: Any, **kwargs: Any) -> None:
    method run (line 481) | async def run(self, request: HttpRequest, **kw: Any) -> HttpResponseBa...
    method _async_stream_response (line 498) | async def _async_stream_response(
    method _run_checks (line 521) | async def _run_checks(self, request: HttpRequest) -> Optional[HttpResp...
    method _run_authentication (line 543) | async def _run_authentication(self, request: HttpRequest) -> Optional[...
  class PathView (line 563) | class PathView:
    method __init__ (line 564) | def __init__(self) -> None:
    method add_operation (line 569) | def add_operation(
    method clone (line 628) | def clone(self) -> "PathView":
    method get_view (line 641) | def get_view(self) -> Callable:
    method _sync_view (line 669) | def _sync_view(self, request: HttpRequest, *a: Any, **kw: Any) -> Http...
    method _async_view (line 675) | async def _async_view(
    method _find_operation (line 685) | def _find_operation(self, request: HttpRequest) -> Optional[Operation]:
    method _not_allowed (line 691) | def _not_allowed(self) -> HttpResponse:
  class ResponseObject (line 698) | class ResponseObject:
    method __init__ (line 701) | def __init__(self, response: HttpResponse) -> None:

FILE: ninja/orm/factory.py
  class SchemaFactory (line 30) | class SchemaFactory:
    method __init__ (line 31) | def __init__(self) -> None:
    method create_schema (line 35) | def create_schema(
    method get_key (line 101) | def get_key(
    method _get_unique_name (line 123) | def _get_unique_name(self, name: str) -> str:
    method _selected_model_fields (line 131) | def _selected_model_fields(
    method _model_fields (line 158) | def _model_fields(self, model: Type[Model]) -> Iterator[DjangoField]:

FILE: ninja/orm/fields.py
  function title_if_lower (line 22) | def title_if_lower(s: str) -> str:
  class AnyObject (line 28) | class AnyObject:
    method __get_pydantic_core_schema__ (line 30) | def __get_pydantic_core_schema__(
    method __get_pydantic_json_schema__ (line 36) | def __get_pydantic_json_schema__(
    method validate (line 42) | def validate(cls, value: Any, _: Any) -> Any:
  function register_field (line 85) | def register_field(django_field: str, python_type: Any) -> None:
  function create_m2m_link_type (line 90) | def create_m2m_link_type(type_: Type[TModel]) -> Type[TModel]:
  function get_schema_field (line 117) | def get_schema_field(
  function get_related_field_schema (line 201) | def get_related_field_schema(field: DjangoField, *, depth: int) -> Tuple...

FILE: ninja/orm/metaclass.py
  class MetaConf (line 16) | class MetaConf:
    method from_schema_class (line 23) | def from_schema_class(name: str, namespace: dict) -> "MetaConf":
  class ModelSchemaMetaclass (line 66) | class ModelSchemaMetaclass(ResolverMetaclass):
    method __new__ (line 68) | def __new__(
  class ModelSchema (line 119) | class ModelSchema(Schema, metaclass=ModelSchemaMetaclass):

FILE: ninja/orm/shortcuts.py
  function S (line 17) | def S(model: Any, **kwargs: Any) -> Type[Schema]:
  function L (line 21) | def L(model: Any, **kwargs: Any) -> List[Any]:

FILE: ninja/pagination.py
  class PaginationBase (line 39) | class PaginationBase(ABC):
    class Input (line 40) | class Input(Schema):
    class Output (line 45) | class Output(Schema):
    method __init__ (line 51) | def __init__(self, *, pass_parameter: Optional[str] = None, **kwargs: ...
    method paginate_queryset (line 55) | def paginate_queryset(
    method _items_count (line 64) | def _items_count(self, queryset: QuerySet) -> int:
  class AsyncPaginationBase (line 76) | class AsyncPaginationBase(PaginationBase):
    method apaginate_queryset (line 78) | async def apaginate_queryset(
    method _aitems_count (line 87) | async def _aitems_count(self, queryset: QuerySet) -> int:
  class LimitOffsetPagination (line 94) | class LimitOffsetPagination(AsyncPaginationBase):
    class Input (line 95) | class Input(Schema):
    method paginate_queryset (line 107) | def paginate_queryset(
    method apaginate_queryset (line 121) | async def apaginate_queryset(
  class PageNumberPagination (line 140) | class PageNumberPagination(AsyncPaginationBase):
    class Input (line 141) | class Input(Schema):
    method __init__ (line 145) | def __init__(
    method _get_page_size (line 155) | def _get_page_size(self, requested_page_size: Optional[int]) -> int:
    method paginate_queryset (line 161) | def paginate_queryset(
    method apaginate_queryset (line 175) | async def apaginate_queryset(
  class CursorPagination (line 196) | class CursorPagination(AsyncPaginationBase):
    method __init__ (line 202) | def __init__(
    class Input (line 223) | class Input(Schema):
    class Output (line 227) | class Output(Schema):
    class Cursor (line 232) | class Cursor(BaseModel):
      method validate_individual_queryparam (line 265) | def validate_individual_queryparam(cls, value: Any) -> Any:
      method from_encoded_param (line 277) | def from_encoded_param(
      method encode_as_param (line 295) | def encode_as_param(self) -> str:
    method _reverse_order (line 306) | def _reverse_order(order: Tuple[str, ...]) -> Tuple[str, ...]:
    method _get_position (line 318) | def _get_position(self, item: Any) -> str:
    method _get_page_size (line 326) | def _get_page_size(self, requested_page_size: Optional[int]) -> int:
    method _build_next_cursor (line 338) | def _build_next_cursor(
    method _build_previous_cursor (line 373) | def _build_previous_cursor(
    method _add_cursor_to_URL (line 418) | def _add_cursor_to_URL(url: str, cursor: Optional[Cursor]) -> Optional...
    method _order_queryset (line 438) | def _order_queryset(self, queryset: QuerySet, cursor: Cursor) -> Query...
    method _find_position (line 450) | def _find_position(self, queryset: QuerySet, cursor: Cursor) -> QuerySet:
    method paginate_queryset (line 461) | def paginate_queryset(
    method apaginate_queryset (line 510) | async def apaginate_queryset(
  function paginate (line 566) | def paginate(
  function _inject_pagination (line 601) | def _inject_pagination(
  class RouterPaginated (line 702) | class RouterPaginated(Router):
    method __init__ (line 703) | def __init__(self, *args: Any, **kwargs: Any) -> None:
    method add_api_operation (line 707) | def add_api_operation(
  function make_response_paginated (line 720) | def make_response_paginated(paginator: PaginationBase, op: Operation) ->...
  function _find_collection_response (line 754) | def _find_collection_response(op: Operation) -> Tuple[int, Any]:

FILE: ninja/params/__init__.py
  class ParamShortcut (line 26) | class ParamShortcut:
    method __init__ (line 27) | def __init__(self, base_func: Callable[..., Any]) -> None:
    method __call__ (line 30) | def __call__(self, *args: Any, **kwargs: Any) -> Any:
    method __getitem__ (line 33) | def __getitem__(self, args: Any) -> Any:
  function P (line 77) | def P(

FILE: ninja/params/functions.py
  function Path (line 11) | def Path(  # noqa: N802
  function Query (line 50) | def Query(  # noqa: N802
  function Header (line 89) | def Header(  # noqa: N802
  function Cookie (line 128) | def Cookie(  # noqa: N802
  function Body (line 167) | def Body(  # noqa: N802
  function Form (line 206) | def Form(  # noqa: N802
  function File (line 245) | def File(  # noqa: N802

FILE: ninja/params/models.py
  class ParamModel (line 41) | class ParamModel(BaseModel, ABC):
    method get_request_data (line 46) | def get_request_data(
    method resolve (line 52) | def resolve(
    method _map_data_paths (line 66) | def _map_data_paths(cls, data: DictStrAny) -> DictStrAny:
    method _map_data_path (line 77) | def _map_data_path(
  class QueryModel (line 87) | class QueryModel(ParamModel):
    method get_request_data (line 89) | def get_request_data(
  class PathModel (line 96) | class PathModel(ParamModel):
    method get_request_data (line 98) | def get_request_data(
  class HeaderModel (line 104) | class HeaderModel(ParamModel):
    method get_request_data (line 108) | def get_request_data(
  class CookieModel (line 119) | class CookieModel(ParamModel):
    method get_request_data (line 121) | def get_request_data(
  class BodyModel (line 127) | class BodyModel(ParamModel):
    method get_request_data (line 131) | def get_request_data(
  class FormModel (line 151) | class FormModel(ParamModel):
    method get_request_data (line 153) | def get_request_data(
  class FileModel (line 160) | class FileModel(ParamModel):
    method get_request_data (line 162) | def get_request_data(
  class _HttpRequest (line 169) | class _HttpRequest(HttpRequest):
  class _MultiPartBodyModel (line 173) | class _MultiPartBodyModel(BodyModel):
    method get_request_data (line 177) | def get_request_data(
  class Param (line 193) | class Param(FieldInfo):  # type: ignore[misc]
    method __init__ (line 194) | def __init__(
    method _param_source (line 251) | def _param_source(cls) -> str:
  class Path (line 256) | class Path(Param):  # type: ignore[misc]
  class Query (line 260) | class Query(Param):  # type: ignore[misc]
  class Header (line 264) | class Header(Param):  # type: ignore[misc]
  class Cookie (line 268) | class Cookie(Param):  # type: ignore[misc]
  class Body (line 272) | class Body(Param):  # type: ignore[misc]
  class Form (line 276) | class Form(Param):  # type: ignore[misc]
  class File (line 280) | class File(Param):  # type: ignore[misc]
  class _MultiPartBody (line 284) | class _MultiPartBody(Param):  # type: ignore[misc]
    method _param_source (line 288) | def _param_source(cls) -> str:

FILE: ninja/parser.py
  class Parser (line 12) | class Parser:
    method parse_body (line 15) | def parse_body(self, request: HttpRequest) -> DictStrAny:
    method parse_querydict (line 18) | def parse_querydict(

FILE: ninja/patch_dict.py
  class ModelToDict (line 20) | class ModelToDict(dict):
    method __get_pydantic_core_schema__ (line 25) | def __get_pydantic_core_schema__(cls, _source: Any, _handler: Any) -> ...
    method _validate (line 32) | def _validate(cls, input_value: Any) -> Any:
  function get_schema_annotations (line 36) | def get_schema_annotations(schema_cls: Type[Any]) -> Dict[str, Any]:
  function create_patch_schema (line 48) | def create_patch_schema(schema_cls: Type[Any]) -> Type[ModelToDict]:
  class PatchDictUtil (line 67) | class PatchDictUtil:
    method __getitem__ (line 68) | def __getitem__(self, schema_cls: Any) -> Any:
  class PatchDict (line 76) | class PatchDict(Dict[Any, Any], Generic[T]):

FILE: ninja/renderers.py
  class BaseRenderer (line 11) | class BaseRenderer:
    method render (line 15) | def render(self, request: HttpRequest, data: Any, *, response_status: ...
  class JSONRenderer (line 19) | class JSONRenderer(BaseRenderer):
    method render (line 24) | def render(self, request: HttpRequest, data: Any, *, response_status: ...

FILE: ninja/responses.py
  class Status (line 25) | class Status(Generic[T]):
    method __init__ (line 35) | def __init__(self, status_code: int, value: T):
  class NinjaJSONEncoder (line 40) | class NinjaJSONEncoder(DjangoJSONEncoder):
    method default (line 41) | def default(self, o: Any) -> Any:
  class Response (line 53) | class Response(JsonResponse):
    method __init__ (line 54) | def __init__(self, data: Any, **kwargs: Any) -> None:
  function resp_codes (line 58) | def resp_codes(from_code: int, to_code: int) -> FrozenSet[int]:

FILE: ninja/router.py
  class RouterMount (line 35) | class RouterMount:
  class BoundRouter (line 59) | class BoundRouter:
    method __init__ (line 67) | def __init__(self, mount: RouterMount, api: "NinjaAPI") -> None:
    method _bind_operations (line 116) | def _bind_operations(self) -> None:
    method urls_paths (line 170) | def urls_paths(self, prefix: str) -> Iterator[URLPattern]:
  class Router (line 192) | class Router:
    method __init__ (line 193) | def __init__(
    method _freeze (line 217) | def _freeze(self) -> None:
    method _check_not_frozen (line 223) | def _check_not_frozen(self) -> None:
    method get (line 231) | def get(
    method post (line 271) | def post(
    method delete (line 311) | def delete(
    method patch (line 351) | def patch(
    method put (line 391) | def put(
    method api_operation (line 431) | def api_operation(
    method add_api_operation (line 477) | def add_api_operation(
    method urls_paths (line 545) | def urls_paths(
    method add_router (line 576) | def add_router(
    method add_decorator (line 601) | def add_decorator(
    method build_routers (line 619) | def build_routers(
    method _apply_decorators_to_operations (line 685) | def _apply_decorators_to_operations(self) -> None:

FILE: ninja/schema.py
  class DjangoGetter (line 53) | class DjangoGetter:
    method __init__ (line 56) | def __init__(self, obj: Any, schema_cls: Type[S], context: Any = None):
    method __getattr__ (line 61) | def __getattr__(self, key: str) -> Any:
    method _convert_result (line 92) | def _convert_result(self, result: Any) -> Any:
    method __repr__ (line 109) | def __repr__(self) -> str:
  class Resolver (line 113) | class Resolver:
    method __init__ (line 119) | def __init__(self, func: Union[Callable, staticmethod]):
    method __call__ (line 130) | def __call__(self, getter: DjangoGetter) -> Any:
  class ResolverMetaclass (line 159) | class ResolverMetaclass(ModelMetaclass):
    method __new__ (line 163) | def __new__(cls, name, bases, namespace, **kwargs):
  class NinjaGenerateJsonSchema (line 186) | class NinjaGenerateJsonSchema(GenerateJsonSchema):
    method default_schema (line 187) | def default_schema(self, schema: Any) -> JsonSchemaValue:
  class Schema (line 209) | class Schema(BaseModel, metaclass=ResolverMetaclass):
    method _run_root_validator (line 214) | def _run_root_validator(
    method from_orm (line 230) | def from_orm(cls: Type[S], obj: Any, **kw: Any) -> S:
    method dict (line 233) | def dict(self, *a: Any, **kw: Any) -> DictStrAny:
    method json_schema (line 238) | def json_schema(cls) -> DictStrAny:
    method schema (line 242) | def schema(cls) -> DictStrAny:  # type: ignore

FILE: ninja/security/apikey.py
  class APIKeyBase (line 13) | class APIKeyBase(AuthBase, ABC):
    method __init__ (line 17) | def __init__(self) -> None:
    method __call__ (line 21) | def __call__(self, request: HttpRequest) -> Optional[Any]:
    method _get_key (line 26) | def _get_key(self, request: HttpRequest) -> Optional[str]:
    method authenticate (line 30) | def authenticate(self, request: HttpRequest, key: Optional[str]) -> Op...
  class APIKeyQuery (line 34) | class APIKeyQuery(APIKeyBase, ABC):
    method _get_key (line 37) | def _get_key(self, request: HttpRequest) -> Optional[str]:
  class APIKeyCookie (line 41) | class APIKeyCookie(APIKeyBase, ABC):
    method __init__ (line 44) | def __init__(self, csrf: bool = True) -> None:
    method _get_key (line 48) | def _get_key(self, request: HttpRequest) -> Optional[str]:
  class APIKeyHeader (line 57) | class APIKeyHeader(APIKeyBase, ABC):
    method _get_key (line 60) | def _get_key(self, request: HttpRequest) -> Optional[str]:

FILE: ninja/security/base.py
  class SecuritySchema (line 12) | class SecuritySchema(dict):
    method __init__ (line 13) | def __init__(self, type: str, **kwargs: Any) -> None:
  class AuthBase (line 17) | class AuthBase(ABC):
    method __init__ (line 18) | def __init__(self) -> None:
    method __call__ (line 34) | def __call__(self, request: HttpRequest) -> Optional[Any]:

FILE: ninja/security/http.py
  class HttpAuthBase (line 18) | class HttpAuthBase(AuthBase, ABC):
  class HttpBearer (line 22) | class HttpBearer(HttpAuthBase, ABC):
    method __call__ (line 26) | def __call__(self, request: HttpRequest) -> Optional[Any]:
    method authenticate (line 41) | def authenticate(self, request: HttpRequest, token: str) -> Optional[A...
  class DecodeError (line 45) | class DecodeError(Exception):
  class HttpBasicAuth (line 49) | class HttpBasicAuth(HttpAuthBase, ABC):  # TODO: maybe HttpBasicAuthBase
    method __call__ (line 53) | def __call__(self, request: HttpRequest) -> Optional[Any]:
    method authenticate (line 68) | def authenticate(
    method decode_authorization (line 73) | def decode_authorization(self, value: str) -> Tuple[str, str]:

FILE: ninja/security/session.py
  class SessionAuth (line 11) | class SessionAuth(APIKeyCookie):
    method authenticate (line 16) | def authenticate(self, request: HttpRequest, key: Optional[str]) -> Op...
  class SessionAuthSuperUser (line 23) | class SessionAuthSuperUser(APIKeyCookie):
    method authenticate (line 28) | def authenticate(self, request: HttpRequest, key: Optional[str]) -> Op...
  class SessionAuthIsStaff (line 36) | class SessionAuthIsStaff(SessionAuthSuperUser):
    method authenticate (line 37) | def authenticate(self, request: HttpRequest, key: Optional[str]) -> Op...

FILE: ninja/signature/details.py
  class ViewSignature (line 42) | class ViewSignature:
    method __init__ (line 48) | def __init__(self, path: str, view_func: Callable[..., Any]) -> None:
    method _validate_view_path_params (line 102) | def _validate_view_path_params(self) -> None:
    method _create_models (line 126) | def _create_models(self) -> TModels:
    method _args_flatten_map (line 187) | def _args_flatten_map(self, args: List[FuncParam]) -> Dict[str, Tuple[...
    method _model_flatten_map (line 210) | def _model_flatten_map(self, model: TModel, prefix: str) -> Generator:
    method _get_param_type (line 221) | def _get_param_type(self, name: str, arg: inspect.Parameter) -> FuncPa...
  function _unwrap_union_model (line 310) | def _unwrap_union_model(annotation: Any) -> Any:
  function is_pydantic_model (line 319) | def is_pydantic_model(cls: Any) -> bool:
  function is_collection_type (line 336) | def is_collection_type(annotation: Any) -> bool:
  function detect_collection_fields (line 356) | def detect_collection_fields(

FILE: ninja/signature/utils.py
  function get_typed_signature (line 22) | def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
  function get_typed_annotation (line 39) | def get_typed_annotation(param: inspect.Parameter, globalns: DictStrAny)...
  function make_forwardref (line 46) | def make_forwardref(annotation: str, globalns: DictStrAny) -> Any:
  function get_path_param_names (line 55) | def get_path_param_names(path: str) -> Set[str]:
  function is_async (line 60) | def is_async(callable: Callable[..., Any]) -> bool:
  function has_kwargs (line 68) | def has_kwargs(func: Callable[..., Any]) -> bool:
  function get_args_names (line 75) | def get_args_names(func: Callable[..., Any]) -> List[str]:
  class UUIDStrConverter (line 80) | class UUIDStrConverter(UUIDConverter):
    method to_python (line 83) | def to_python(self, value: str) -> str:  # type: ignore

FILE: ninja/static/ninja/redoc.standalone.js
  function s (line 2) | function s(e){try{l(r.next(e))}catch(e){o(e)}}
  function a (line 2) | function a(e){try{l(r.throw(e))}catch(e){o(e)}}
  function l (line 2) | function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(...
  function b (line 2) | function b(e){return r(this,void 0,void 0,(function*(){const{document:t,...
  function v (line 2) | function v(e,t){switch(t){case c.SpecMajorVersion.OAS3:switch(e){case"Sc...
    method constructor (line 2) | constructor(e,t){g(e),t||(t={}),this.options=t,this.set=[],this.patter...
    method debug (line 2) | debug(){}
    method make (line 2) | make(){const e=this.pattern,t=this.options;if(!t.nocomment&&"#"===e.ch...
    method parseNegate (line 2) | parseNegate(){if(this.options.nonegate)return;const e=this.pattern;let...
    method matchOne (line 2) | matchOne(e,t,n){var r=this.options;this.debug("matchOne",{this:this,fi...
    method braceExpand (line 2) | braceExpand(){return m(this.pattern,this.options)}
    method parse (line 2) | parse(e,t){g(e);const n=this.options;if("**"===e){if(!n.noglobstar)ret...
    method makeRe (line 2) | makeRe(){if(this.regexp||!1===this.regexp)return this.regexp;const e=t...
    method match (line 2) | match(e,t=this.partial){if(this.debug("match",e,this.pattern),this.com...
    method defaults (line 2) | static defaults(e){return r.defaults(e).Minimatch}
  function x (line 2) | function x(e,t,n,r,s,a){let l,p;const m={ref:{leave(i,l,c){if(!c.locatio...
  class p (line 2) | class p{constructor(e,n){this.rawConfig=e,this.configFile=n,this.ignore=...
    method constructor (line 2) | constructor(e,n){this.rawConfig=e,this.configFile=n,this.ignore={},thi...
    method resolveIgnore (line 2) | resolveIgnore(e){if(e&&(0,s.doesYamlFileExist)(e)){this.ignore=(0,o.pa...
    method saveIgnore (line 2) | saveIgnore(){const e=this.configFile?i.dirname(this.configFile):proces...
    method addIgnore (line 2) | addIgnore(e){const t=this.ignore,n=e.location[0];if(void 0===n.pointer...
    method addProblemToIgnore (line 2) | addProblemToIgnore(e){const t=e.location[0];if(void 0===t.pointer)retu...
    method extendTypes (line 2) | extendTypes(e,t){let n=e;for(const e of this.plugins)if(void 0!==e.typ...
    method getRuleSettings (line 2) | getRuleSettings(e,t){this._usedRules.add(e),this._usedVersions.add(t);...
    method getPreprocessorSettings (line 2) | getPreprocessorSettings(e,t){this._usedRules.add(e),this._usedVersions...
    method getDecoratorSettings (line 2) | getDecoratorSettings(e,t){this._usedRules.add(e),this._usedVersions.ad...
    method getUnusedRules (line 2) | getUnusedRules(){const e=[],t=[],n=[];for(const r of Array.from(this._...
    method getRulesForOasVersion (line 2) | getRulesForOasVersion(e){switch(e){case a.SpecMajorVersion.OAS3:const ...
    method skipRules (line 2) | skipRules(e){for(const t of e||[])for(const e of Object.values(a.SpecV...
    method skipPreprocessors (line 2) | skipPreprocessors(e){for(const t of e||[])for(const e of Object.values...
    method skipDecorators (line 2) | skipDecorators(e){for(const t of e||[])for(const e of Object.values(a....
  method constructor (line 2) | constructor(e,t){this.rawConfig=e,this.configFile=t,this.apis=e.apis||{}...
  function a (line 2) | function a(e){if(!e)return;const t={};for(const[n,r]of Object.entries(e)...
  function l (line 2) | function l(e){var t,{plugins:n,extends:o,rules:s,oas2Rules:a,oas3_0Rules...
  function c (line 2) | function c(e){if(!e)return;const t={};for(let n of Object.entries(e)){co...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function u (line 2) | function u(e,t,n,r){const o=n.apis&&Object.values(n.apis).some((t=>t[e])...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  class p (line 2) | class p extends Error{}
    method constructor (line 2) | constructor(e,n){this.rawConfig=e,this.configFile=n,this.ignore={},thi...
    method resolveIgnore (line 2) | resolveIgnore(e){if(e&&(0,s.doesYamlFileExist)(e)){this.ignore=(0,o.pa...
    method saveIgnore (line 2) | saveIgnore(){const e=this.configFile?i.dirname(this.configFile):proces...
    method addIgnore (line 2) | addIgnore(e){const t=this.ignore,n=e.location[0];if(void 0===n.pointer...
    method addProblemToIgnore (line 2) | addProblemToIgnore(e){const t=e.location[0];if(void 0===t.pointer)retu...
    method extendTypes (line 2) | extendTypes(e,t){let n=e;for(const e of this.plugins)if(void 0!==e.typ...
    method getRuleSettings (line 2) | getRuleSettings(e,t){this._usedRules.add(e),this._usedVersions.add(t);...
    method getPreprocessorSettings (line 2) | getPreprocessorSettings(e,t){this._usedRules.add(e),this._usedVersions...
    method getDecoratorSettings (line 2) | getDecoratorSettings(e,t){this._usedRules.add(e),this._usedVersions.ad...
    method getUnusedRules (line 2) | getUnusedRules(){const e=[],t=[],n=[];for(const r of Array.from(this._...
    method getRulesForOasVersion (line 2) | getRulesForOasVersion(e){switch(e){case a.SpecMajorVersion.OAS3:const ...
    method skipRules (line 2) | skipRules(e){for(const t of e||[])for(const e of Object.values(a.SpecV...
    method skipPreprocessors (line 2) | skipPreprocessors(e){for(const t of e||[])for(const e of Object.values...
    method skipDecorators (line 2) | skipDecorators(e){for(const t of e||[])for(const e of Object.values(a....
  method get (line 2) | get(e,t){return o.isBrowser?s.identity:e[t]}
  method stderr (line 2) | stderr(e){return process.stderr.write(e)}
  method info (line 2) | info(e){return o.isBrowser?console.log(e):this.stderr(e)}
  method warn (line 2) | warn(e){return o.isBrowser?console.warn(e):this.stderr(t.colorize.yellow...
  method error (line 2) | error(e){return o.isBrowser?console.error(e):this.stderr(t.colorize.red(...
  function s (line 2) | function s(e){try{l(r.next(e))}catch(e){o(e)}}
  function a (line 2) | function a(e){try{l(r.throw(e))}catch(e){o(e)}}
  function l (line 2) | function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(...
  method constructor (line 2) | constructor(e){this.accessTokens={},this.region=this.loadRegion(e),this....
  method loadRegion (line 2) | loadRegion(e){if(e&&!l.DOMAINS[e])throw new Error(`Invalid argument: reg...
  method getRegion (line 2) | getRegion(){return this.region}
  method hasTokens (line 2) | hasTokens(){return(0,u.isNotEmptyObject)(this.accessTokens)}
  method hasToken (line 2) | hasToken(){return!!this.accessTokens[this.region]}
  method getAuthorizationHeader (line 2) | getAuthorizationHeader(){return r(this,void 0,void 0,(function*(){return...
  method setAccessTokens (line 2) | setAccessTokens(e){this.accessTokens=e}
  method loadTokens (line 2) | loadTokens(){const e=(0,o.resolve)((0,s.homedir)(),d),t=this.readCredent...
  method getAllTokens (line 2) | getAllTokens(){return Object.entries(this.accessTokens).filter((([e])=>l...
  method getValidTokens (line 2) | getValidTokens(){return r(this,void 0,void 0,(function*(){const e=this.g...
  method getTokens (line 2) | getTokens(){return r(this,void 0,void 0,(function*(){return this.hasToke...
  method isAuthorizedWithRedoclyByRegion (line 2) | isAuthorizedWithRedoclyByRegion(){return r(this,void 0,void 0,(function*...
  method isAuthorizedWithRedocly (line 2) | isAuthorizedWithRedocly(){return r(this,void 0,void 0,(function*(){retur...
  method readCredentialsFile (line 2) | readCredentialsFile(e){return(0,i.existsSync)(e)?JSON.parse((0,i.readFil...
  method verifyToken (line 2) | verifyToken(e,t,n=!1){return r(this,void 0,void 0,(function*(){return th...
  method login (line 2) | login(e,t=!1){return r(this,void 0,void 0,(function*(){const n=(0,o.reso...
  method logout (line 2) | logout(){const e=(0,o.resolve)((0,s.homedir)(),d);(0,i.existsSync)(e)&&(...
  function s (line 2) | function s(e){try{l(r.next(e))}catch(e){o(e)}}
  function a (line 2) | function a(e){try{l(r.throw(e))}catch(e){o(e)}}
  function l (line 2) | function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(...
  method constructor (line 2) | constructor(e,t){this.accessTokens=e,this.region=t}
  method accessToken (line 2) | get accessToken(){return(0,s.isNotEmptyObject)(this.accessTokens)&&this....
  method getBaseUrl (line 2) | getBaseUrl(e=o.DEFAULT_REGION){return`https://api.${o.DOMAINS[e]}/regist...
  method setAccessTokens (line 2) | setAccessTokens(e){return this.accessTokens=e,this}
  method request (line 2) | request(e="",t={},n){var o,s;return r(this,void 0,void 0,(function*(){co...
  method authStatus (line 2) | authStatus(e,t,n=!1){return r(this,void 0,void 0,(function*(){try{const ...
  method prepareFileUpload (line 2) | prepareFileUpload({organizationId:e,name:t,version:n,filesHash:i,filenam...
  method pushApi (line 2) | pushApi({organizationId:e,name:t,version:n,rootFilePath:i,filePaths:o,br...
  function i (line 2) | function i(e,t){return""===e&&(e="#/"),"/"===e[e.length-1]?e+t:e+"/"+t}
  class o (line 2) | class o{constructor(e,t){this.source=e,this.pointer=t}child(e){return ne...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e){return decodeURIComponent(e.replace(/~1/g,"/").replace(/~0...
  function a (line 2) | function a(e){return"number"==typeof e?e:e.replace(/~/g,"~0").replace(/\...
  function s (line 2) | function s(e){try{l(r.next(e))}catch(e){o(e)}}
  function a (line 2) | function a(e){try{l(r.throw(e))}catch(e){o(e)}}
  function l (line 2) | function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(...
  class c (line 2) | class c{constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  class u (line 2) | class u extends Error{constructor(e){super(e.message),this.originalError...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  class d (line 2) | class d extends Error{constructor(e,t){super(e.message.split("\n")[0]),t...
    method constructor (line 2) | constructor(e,t){super(e.message.split("\n")[0]),this.originalError=e,...
  function f (line 2) | function f(e,t){return e+"::"+t}
  function h (line 2) | function h(e,t){return{prev:e,node:t}}
  method constructor (line 2) | constructor(e={http:{headers:[]}}){this.config=e,this.cache=new Map}
  method getFiles (line 2) | getFiles(){return new Set(Array.from(this.cache.keys()))}
  method resolveExternalRef (line 2) | resolveExternalRef(e,t){return(0,s.isAbsoluteUrl)(t)?t:e&&(0,s.isAbsolut...
  method loadExternalRef (line 2) | loadExternalRef(e){return r(this,void 0,void 0,(function*(){try{if((0,s....
  method parseDocument (line 2) | parseDocument(e,t=!1){var n;const r=e.absoluteRef.substr(e.absoluteRef.l...
  method resolveDocument (line 2) | resolveDocument(e,t,n=!1){return r(this,void 0,void 0,(function*(){const...
  function v (line 2) | function v(e,t,i){return r(this,void 0,void 0,(function*(){if(function(e...
    method constructor (line 2) | constructor(e,t){g(e),t||(t={}),this.options=t,this.set=[],this.patter...
    method debug (line 2) | debug(){}
    method make (line 2) | make(){const e=this.pattern,t=this.options;if(!t.nocomment&&"#"===e.ch...
    method parseNegate (line 2) | parseNegate(){if(this.options.nonegate)return;const e=this.pattern;let...
    method matchOne (line 2) | matchOne(e,t,n){var r=this.options;this.debug("matchOne",{this:this,fi...
    method braceExpand (line 2) | braceExpand(){return m(this.pattern,this.options)}
    method parse (line 2) | parse(e,t){g(e);const n=this.options;if("**"===e){if(!n.noglobstar)ret...
    method makeRe (line 2) | makeRe(){if(this.regexp||!1===this.regexp)return this.regexp;const e=t...
    method match (line 2) | match(e,t=this.partial){if(this.debug("match",e,this.pattern),this.com...
    method defaults (line 2) | static defaults(e){return r.defaults(e).Minimatch}
  function i (line 2) | function i(e,t,n){var i;const o=e.error;o instanceof r.YamlParseError&&t...
  method leave (line 2) | leave(e,{report:t,location:n},r){void 0===r.node&&i(r,t,n)}
  method DiscriminatorMapping (line 2) | DiscriminatorMapping(e,{report:t,resolve:n,location:r}){for(const o of O...
  function t (line 2) | function t(t,n,r){var i;e.set(t.absolutePointer,{used:(null===(i=e.get(t...
  method leave (line 2) | leave(t,{type:n,resolve:r,key:i}){if(["Schema","Parameter","Response","S...
  method leave (line 2) | leave(t,n){const i=n.getVisitorData();i.removedCount=0;const o=new Set;e...
  method Schema (line 2) | Schema(e,{location:n,key:r}){e.allOf||t(n,"definitions",r.toString())}
  method Parameter (line 2) | Parameter(e,{location:n,key:r}){t(n,"parameters",r.toString())}
  method Response (line 2) | Response(e,{location:n,key:r}){t(n,"responses",r.toString())}
  method SecurityScheme (line 2) | SecurityScheme(e,{location:n,key:r}){t(n,"securityDefinitions",r.toStrin...
  function t (line 2) | function t(t,n,r){var i;e.set(t.absolutePointer,{used:(null===(i=e.get(t...
  method leave (line 2) | leave(t,{type:n,resolve:r,key:i}){if(["Schema","Header","Parameter","Res...
  method leave (line 2) | leave(t,n){const i=n.getVisitorData();i.removedCount=0,e.forEach((e=>{co...
  method Schema (line 2) | Schema(e,{location:n,key:r}){e.allOf||t(n,"schemas",r.toString())}
  method Parameter (line 2) | Parameter(e,{location:n,key:r}){t(n,"parameters",r.toString())}
  method Response (line 2) | Response(e,{location:n,key:r}){t(n,"responses",r.toString())}
  method Example (line 2) | Example(e,{location:n,key:r}){t(n,"examples",r.toString())}
  method RequestBody (line 2) | RequestBody(e,{location:n,key:r}){t(n,"requestBodies",r.toString())}
  method Header (line 2) | Header(e,{location:n,key:r}){t(n,"headers",r.toString())}
  method allowed (line 2) | allowed(){return["http","ws","kafka","anypointmq","amqp","amqp1","mqtt",...
  method allowed (line 2) | allowed(){return["http","ws","kafka","anypointmq","amqp","amqp1","mqtt",...
  method allowed (line 2) | allowed(){return["http","ws","kafka","anypointmq","amqp","amqp1","mqtt",...
  method allowed (line 2) | allowed(){return["http","ws","kafka","anypointmq","amqp","amqp1","mqtt",...
  method required (line 2) | required(e){switch(null==e?void 0:e.type){case"apiKey":return["type","in...
  method allowed (line 2) | allowed(e){switch(null==e?void 0:e.type){case"apiKey":return["type","in"...
  function i (line 2) | function i(e){if(e.additionalProperties&&(e.additionalProperties=o(e.add...
  function o (line 2) | function o(e){if("string"==typeof e){if(!r[e])throw new Error(`Unknown t...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  method required (line 2) | required(e){return e&&e.in?"body"===e.in?["name","in","schema"]:"array"=...
  method required (line 2) | required(e){return e&&"array"===e.type?["type","items"]:["type"]}
  method required (line 2) | required(e){return e&&"array"===e.type?["type","items"]:["type"]}
  method required (line 2) | required(e){switch(null==e?void 0:e.type){case"apiKey":return["type","na...
  method allowed (line 2) | allowed(e){switch(null==e?void 0:e.type){case"basic":return["type","desc...
  method required (line 2) | required(e){switch(null==e?void 0:e.type){case"apiKey":return["type","na...
  method allowed (line 2) | allowed(e){switch(null==e?void 0:e.type){case"apiKey":return["type","nam...
  method required (line 2) | required(e){switch(null==e?void 0:e.type){case"apiKey":return["type","na...
  method allowed (line 2) | allowed(e){switch(null==e?void 0:e.type){case"apiKey":return["type","nam...
  function s (line 2) | function s(e){try{l(r.next(e))}catch(e){o(e)}}
  function a (line 2) | function a(e){try{l(r.throw(e))}catch(e){o(e)}}
  function l (line 2) | function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(...
  function f (line 2) | function f(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}
  function h (line 2) | function h(e,t){return t.match(/^https?:\/\//)||(e=e.replace(/^https?:\/...
  function m (line 2) | function m(e){return"string"==typeof e}
  function g (line 2) | function g(e){return!!e}
  function y (line 2) | function y(e,t){return`${void 0!==t?`${t}.`:""}${e}`}
  function o (line 2) | function o(e,t,i,s,a=[]){if(a.includes(t))return;a=[...a,t];const l=new ...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e,t){if(Array.isArray(t)){const n=t.find((t=>e[t]))||void 0;r...
  function a (line 2) | function a(e,r,l,c=0){const u=Object.keys(t);if(0===c)u.push("any"),u.pu...
  function a (line 2) | function a(e){var t,n;const r={};for(;e.parent;)(null===(t=e.parent.acti...
  function N (line 2) | function N(e,t,r,i,o,s){e(t,{report:$.bind(void 0,o,s),resolve:A,rawNode...
  function $ (line 2) | function $(e,t,n){const r=(n.location?Array.isArray(n.location)?n.locati...
  function L (line 2) | function L(e){return u.visitorsData[e]=u.visitorsData[e]||{},u.visitorsD...
  function c (line 2) | function c(e){return parseInt(e,10)==e?parseInt(e,10):e.charCodeAt(0)}
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function u (line 2) | function u(e){return e.split(i).join("\\").split(o).join("{").split(s).j...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  function p (line 2) | function p(e){if(!e)return[""];var t=[],n=r("{","}",e);if(!n)return e.sp...
    method constructor (line 2) | constructor(e,n){this.rawConfig=e,this.configFile=n,this.ignore={},thi...
    method resolveIgnore (line 2) | resolveIgnore(e){if(e&&(0,s.doesYamlFileExist)(e)){this.ignore=(0,o.pa...
    method saveIgnore (line 2) | saveIgnore(){const e=this.configFile?i.dirname(this.configFile):proces...
    method addIgnore (line 2) | addIgnore(e){const t=this.ignore,n=e.location[0];if(void 0===n.pointer...
    method addProblemToIgnore (line 2) | addProblemToIgnore(e){const t=e.location[0];if(void 0===t.pointer)retu...
    method extendTypes (line 2) | extendTypes(e,t){let n=e;for(const e of this.plugins)if(void 0!==e.typ...
    method getRuleSettings (line 2) | getRuleSettings(e,t){this._usedRules.add(e),this._usedVersions.add(t);...
    method getPreprocessorSettings (line 2) | getPreprocessorSettings(e,t){this._usedRules.add(e),this._usedVersions...
    method getDecoratorSettings (line 2) | getDecoratorSettings(e,t){this._usedRules.add(e),this._usedVersions.ad...
    method getUnusedRules (line 2) | getUnusedRules(){const e=[],t=[],n=[];for(const r of Array.from(this._...
    method getRulesForOasVersion (line 2) | getRulesForOasVersion(e){switch(e){case a.SpecMajorVersion.OAS3:const ...
    method skipRules (line 2) | skipRules(e){for(const t of e||[])for(const e of Object.values(a.SpecV...
    method skipPreprocessors (line 2) | skipPreprocessors(e){for(const t of e||[])for(const e of Object.values...
    method skipDecorators (line 2) | skipDecorators(e){for(const t of e||[])for(const e of Object.values(a....
  function d (line 2) | function d(e){return"{"+e+"}"}
    method constructor (line 2) | constructor(e,t){super(e.message.split("\n")[0]),this.originalError=e,...
  function f (line 2) | function f(e){return/^-?0\d/.test(e)}
  function h (line 2) | function h(e,t){return e<=t}
  function m (line 2) | function m(e,t){return e>=t}
  function g (line 2) | function g(e,t){var n=[],i=r("{","}",e);if(!i)return[e];var o=i.pre,a=i....
  method constructor (line 2) | constructor(t,n){super(t,h(e,n))}
  class v (line 2) | class v{constructor(e,t){g(e),t||(t={}),this.options=t,this.set=[],this....
    method constructor (line 2) | constructor(e,t){g(e),t||(t={}),this.options=t,this.set=[],this.patter...
    method debug (line 2) | debug(){}
    method make (line 2) | make(){const e=this.pattern,t=this.options;if(!t.nocomment&&"#"===e.ch...
    method parseNegate (line 2) | parseNegate(){if(this.options.nonegate)return;const e=this.pattern;let...
    method matchOne (line 2) | matchOne(e,t,n){var r=this.options;this.debug("matchOne",{this:this,fi...
    method braceExpand (line 2) | braceExpand(){return m(this.pattern,this.options)}
    method parse (line 2) | parse(e,t){g(e);const n=this.options;if("**"===e){if(!n.noglobstar)ret...
    method makeRe (line 2) | makeRe(){if(this.regexp||!1===this.regexp)return this.regexp;const e=t...
    method match (line 2) | match(e,t=this.partial){if(this.debug("match",e,this.pattern),this.com...
    method defaults (line 2) | static defaults(e){return r.defaults(e).Minimatch}
  function t (line 2) | function t(e,t,i){e instanceof RegExp&&(e=n(e,i)),t instanceof RegExp&&(...
  function n (line 2) | function n(e,t){var n=t.match(e);return n?n[0]:null}
  function r (line 2) | function r(e,t,n){var r,i,o,s,a,l=n.indexOf(e),c=n.indexOf(t,l+1),u=l;if...
  function i (line 2) | function i(){for(var e=[],t=0;t<arguments.length;t++){var n=arguments[t]...
  function t (line 2) | function t(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Ar...
  function c (line 2) | function c(e,t){var n,r=(t=t||e.decorate||(n=e,function(e){return"functi...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function r (line 2) | function r(){}
  function i (line 2) | function i(e,t,n){this.fn=e,this.context=t,this.once=n||!1}
  function o (line 2) | function o(e,t,r,o,s){if("function"!=typeof r)throw new TypeError("The l...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e,t){0==--e._eventsCount?e._events=new r:delete e._events[t]}
  function a (line 2) | function a(){this._events=new r,this._eventsCount=0}
  function o (line 2) | function o(){return{depthLimit:Number.MAX_SAFE_INTEGER,edgesLimit:Number...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e,t,n,s){var a;void 0===s&&(s=o()),l(e,"",0,[],void 0,0,s);tr...
  function a (line 2) | function a(e,t,n,o){var s=Object.getOwnPropertyDescriptor(o,n);void 0!==...
  function l (line 2) | function l(e,r,i,o,s,c,u){var p;if(c+=1,"object"==typeof e&&null!==e){fo...
  function c (line 2) | function c(e,t){return e<t?-1:e>t?1:0}
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function u (line 2) | function u(e,t,n,s){void 0===s&&(s=o());var a,l=p(e,"",0,[],void 0,0,s)|...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  function p (line 2) | function p(e,i,o,s,l,u,d){var f;if(u+=1,"object"==typeof e&&null!==e){fo...
    method constructor (line 2) | constructor(e,n){this.rawConfig=e,this.configFile=n,this.ignore={},thi...
    method resolveIgnore (line 2) | resolveIgnore(e){if(e&&(0,s.doesYamlFileExist)(e)){this.ignore=(0,o.pa...
    method saveIgnore (line 2) | saveIgnore(){const e=this.configFile?i.dirname(this.configFile):proces...
    method addIgnore (line 2) | addIgnore(e){const t=this.ignore,n=e.location[0];if(void 0===n.pointer...
    method addProblemToIgnore (line 2) | addProblemToIgnore(e){const t=e.location[0];if(void 0===t.pointer)retu...
    method extendTypes (line 2) | extendTypes(e,t){let n=e;for(const e of this.plugins)if(void 0!==e.typ...
    method getRuleSettings (line 2) | getRuleSettings(e,t){this._usedRules.add(e),this._usedVersions.add(t);...
    method getPreprocessorSettings (line 2) | getPreprocessorSettings(e,t){this._usedRules.add(e),this._usedVersions...
    method getDecoratorSettings (line 2) | getDecoratorSettings(e,t){this._usedRules.add(e),this._usedVersions.ad...
    method getUnusedRules (line 2) | getUnusedRules(){const e=[],t=[],n=[];for(const r of Array.from(this._...
    method getRulesForOasVersion (line 2) | getRulesForOasVersion(e){switch(e){case a.SpecMajorVersion.OAS3:const ...
    method skipRules (line 2) | skipRules(e){for(const t of e||[])for(const e of Object.values(a.SpecV...
    method skipPreprocessors (line 2) | skipPreprocessors(e){for(const t of e||[])for(const e of Object.values...
    method skipDecorators (line 2) | skipDecorators(e){for(const t of e||[])for(const e of Object.values(a....
  function d (line 2) | function d(e){return e=void 0!==e?e:function(e,t){return t},function(t,n...
    method constructor (line 2) | constructor(e,t){super(e.message.split("\n")[0]),this.originalError=e,...
  function o (line 2) | function o(e){return" "===e||"\t"===e||"\n"===e||"\r"===e}
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e,t){const n=t;for(;t<e.length;t++)if("?"!=e[t]&&" "!=e[t]);e...
  function a (line 2) | function a(e,t){if(e.length>t+5&&"-"===e[t+1]&&"-"===e[t+2]){for(t+=3;t<...
  function u (line 2) | function u(e,t){let n="",r="",i=!1;for(;t<e.length;t++){if(e[t]===l||e[t...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  function d (line 2) | function d(e,t){const n=r.getAllMatches(e,p),i={};for(let e=0;e<n.length...
    method constructor (line 2) | constructor(e,t){super(e.message.split("\n")[0]),this.originalError=e,...
  function f (line 2) | function f(e,t){if(";"===e[++t])return-1;if("#"===e[t])return function(e...
  function h (line 2) | function h(e,t,n){return{err:{code:e,msg:t,line:n.line||n,col:n.col}}}
  function m (line 2) | function m(e){return r.isName(e)}
  function g (line 2) | function g(e,t){const n=e.substring(0,t).split(/\r?\n/);return{line:n.le...
  function y (line 2) | function y(e){return e.startIndex+e[1].length}
  function s (line 2) | function s(e){this.options=Object.assign({},o,e),!0===this.options.ignor...
  function a (line 2) | function a(e,t,n,r){const i=this.j2x(e,n+1,r.concat(t));return void 0!==...
  function l (line 2) | function l(e){return this.options.indentBy.repeat(e)}
  function c (line 2) | function c(e){return!(!e.startsWith(this.options.attributeNamePrefix)||e...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function t (line 2) | function t(e,s,a,l){let c="",u=!1;for(let p=0;p<e.length;p++){const d=e[...
  function n (line 2) | function n(e){const t=Object.keys(e);for(let n=0;n<t.length;n++){const r...
  function r (line 2) | function r(e,t){let n="";if(e&&!t.ignoreAttributes)for(let r in e){if(!e...
  function i (line 2) | function i(e,t){let n=(e=e.substr(0,e.length-t.textNodeName.length-1)).s...
  function o (line 2) | function o(e,t){if(e&&e.length>0&&t.processEntities)for(let n=0;n<t.enti...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function i (line 2) | function i(e,t){let n="";for(;t<e.length&&"'"!==e[t]&&'"'!==e[t];t++)n+=...
  function o (line 2) | function o(e,t){return"!"===e[t+1]&&"-"===e[t+2]&&"-"===e[t+3]}
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e,t){return"!"===e[t+1]&&"E"===e[t+2]&&"N"===e[t+3]&&"T"===e[...
  function a (line 2) | function a(e,t){return"!"===e[t+1]&&"E"===e[t+2]&&"L"===e[t+3]&&"E"===e[...
  function l (line 2) | function l(e,t){return"!"===e[t+1]&&"A"===e[t+2]&&"T"===e[t+3]&&"T"===e[...
  function c (line 2) | function c(e,t){return"!"===e[t+1]&&"N"===e[t+2]&&"O"===e[t+3]&&"T"===e[...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function u (line 2) | function u(e){if(r.isName(e))return e;throw new Error(`Invalid entity na...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  function l (line 2) | function l(e){const t=Object.keys(e);for(let n=0;n<t.length;n++){const r...
  function c (line 2) | function c(e,t,n,r,i,o,s){if(void 0!==e&&(this.options.trimValues&&!r&&(...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function u (line 2) | function u(e){if(this.options.removeNSPrefix){const t=e.split(":"),n="/"...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  function d (line 2) | function d(e,t,n){if(!0!==this.options.ignoreAttributes&&"string"==typeo...
    method constructor (line 2) | constructor(e,t){super(e.message.split("\n")[0]),this.originalError=e,...
  function h (line 2) | function h(e,t,n){const r=this.options.updateTag(t.tagname,n,t[":@"]);!1...
  function g (line 2) | function g(e,t,n,r){return e&&(void 0===r&&(r=0===t.child.length),void 0...
  function y (line 2) | function y(e,t,n){const r="*."+n;for(const n in e){const i=e[n];if(r===i...
  function b (line 2) | function b(e,t,n,r){const i=e.indexOf(t,n);if(-1===i)throw new Error(r);...
  function v (line 2) | function v(e,t,n,r=">"){const i=function(e,t,n=">"){let r,i="";for(let o...
    method constructor (line 2) | constructor(e,t){g(e),t||(t={}),this.options=t,this.set=[],this.patter...
    method debug (line 2) | debug(){}
    method make (line 2) | make(){const e=this.pattern,t=this.options;if(!t.nocomment&&"#"===e.ch...
    method parseNegate (line 2) | parseNegate(){if(this.options.nonegate)return;const e=this.pattern;let...
    method matchOne (line 2) | matchOne(e,t,n){var r=this.options;this.debug("matchOne",{this:this,fi...
    method braceExpand (line 2) | braceExpand(){return m(this.pattern,this.options)}
    method parse (line 2) | parse(e,t){g(e);const n=this.options;if("**"===e){if(!n.noglobstar)ret...
    method makeRe (line 2) | makeRe(){if(this.regexp||!1===this.regexp)return this.regexp;const e=t...
    method match (line 2) | match(e,t=this.partial){if(this.debug("match",e,this.pattern),this.com...
    method defaults (line 2) | static defaults(e){return r.defaults(e).Minimatch}
  function x (line 2) | function x(e,t,n){const r=n;let i=1;for(;n<e.length;n++)if("<"===e[n])if...
  function w (line 2) | function w(e,t,n){if(t&&"string"==typeof e){const t=e.trim();return"true...
    method constructor (line 2) | constructor(e){super(e),this.name="S2OError"}
  method constructor (line 2) | constructor(e){this.options=e,this.currentNode=null,this.tagsNodeStack=[...
  method constructor (line 2) | constructor(e){this.externalEntities={},this.options=r(e)}
  method parse (line 2) | parse(e,t){if("string"==typeof e);else{if(!e.toString)throw new Error("X...
  method addEntity (line 2) | addEntity(e,t){if(-1!==t.indexOf("&"))throw new Error("Entity value can'...
  function n (line 2) | function n(e,t,s){let a;const l={};for(let c=0;c<e.length;c++){const u=e...
  function r (line 2) | function r(e){const t=Object.keys(e);for(let e=0;e<t.length;e++){const n...
  function i (line 2) | function i(e,t,n,r){if(t){const i=Object.keys(t),o=i.length;for(let s=0;...
  function o (line 2) | function o(e,t){const{textNodeName:n}=t,r=Object.keys(e).length;return 0...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  method constructor (line 2) | constructor(e){this.tagname=e,this.child=[],this[":@"]={}}
  method add (line 2) | add(e,t){"__proto__"===e&&(e="#__proto__"),this.child.push({[e]:t})}
  method addChild (line 2) | addChild(e){"__proto__"===e.tagname&&(e.tagname="#__proto__"),e[":@"]&&O...
  function l (line 2) | function l(e){return r.isMemo(e)?s:a[e.$$typeof]||i}
  function w (line 2) | function w(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t...
    method constructor (line 2) | constructor(e){super(e),this.name="S2OError"}
  function k (line 2) | function k(e){return w(e)===p}
  function o (line 2) | function o(e,t){return function(){throw new Error("Function yaml."+e+" i...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function t (line 2) | function t(e){return null==e}
  function L (line 2) | function L(e){var t,n,o;if(t=e.toString(16).toUpperCase(),e<=255)n="x",o...
  function M (line 2) | function M(e){this.schema=e.schema||o,this.indent=Math.max(1,e.indent||2...
  function F (line 2) | function F(e,t){for(var n,i=r.repeat(" ",t),o=0,s=-1,a="",l=e.length;o<l...
  function z (line 2) | function z(e,t){return"\n"+r.repeat(" ",e.indent*t)}
  function B (line 2) | function B(e){return e===d||e===c}
  function U (line 2) | function U(e){return 32<=e&&e<=126||161<=e&&e<=55295&&8232!==e&&8233!==e...
  function q (line 2) | function q(e){return U(e)&&e!==l&&e!==p&&e!==u}
  function V (line 2) | function V(e,t,n){var r=q(e),i=r&&!B(e);return(n?r:r&&e!==x&&e!==A&&e!==...
  function W (line 2) | function W(e,t){var n,r=e.charCodeAt(t);return r>=55296&&r<=56319&&t+1<e...
  function H (line 2) | function H(e){return/^\n* /.test(e)}
  function Z (line 2) | function Z(e,t,n,r,o){e.dump=function(){if(0===t.length)return e.quoting...
  function J (line 2) | function J(e,t){var n=H(e)?String(t):"",r="\n"===e[e.length-1];return n+...
  function ee (line 2) | function ee(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}
  function te (line 2) | function te(e,t){if(""===e||" "===e[0])return e;for(var n,r,i=/ [^ ]/g,o...
  function ne (line 2) | function ne(e,t,n,r){var i,o,s,a="",l=e.tag;for(i=0,o=n.length;i<o;i+=1)...
  function re (line 2) | function re(e,t,n){var r,o,l,c,u,p;for(l=0,c=(o=n?e.explicitTypes:e.impl...
  function ie (line 2) | function ie(e,t,n,r,o,a,l){e.tag=null,e.dump=n,re(e,n,!1)||re(e,n,!0);va...
  function oe (line 2) | function oe(e,t){var n,r,i=[],o=[];for(se(e,i,o),n=0,r=o.length;n<r;n+=1...
  function se (line 2) | function se(e,t,n){var r,i,o;if(null!==e&&"object"==typeof e)if(-1!==(i=...
  function t (line 2) | function t(e,t){var n="",r=e.reason||"(unknown reason)";return e.mark?(e...
  function n (line 2) | function n(e,n){Error.call(this),this.name="YAMLException",this.reason=e...
  function x (line 2) | function x(e){return Object.prototype.toString.call(e)}
  function w (line 2) | function w(e){return 10===e||13===e}
    method constructor (line 2) | constructor(e){super(e),this.name="S2OError"}
  function k (line 2) | function k(e){return 9===e||32===e}
  function S (line 2) | function S(e){return 9===e||32===e||10===e||13===e}
  function E (line 2) | function E(e){return 44===e||91===e||93===e||123===e||125===e}
  function O (line 2) | function O(e){var t;return 48<=e&&e<=57?e-48:97<=(t=32|e)&&t<=102?t-97+1...
  function _ (line 2) | function _(e){return 48===e?"\0":97===e?"":98===e?"\b":116===e||9===e?"...
  function A (line 2) | function A(e){return e<=65535?String.fromCharCode(e):String.fromCharCode...
  function T (line 2) | function T(e,t){this.input=e,this.filename=t.filename||null,this.schema=...
  function I (line 2) | function I(e,t){var n={name:e.filename,buffer:e.input.slice(0,-1),positi...
  function R (line 2) | function R(e,t){throw I(e,t)}
  function N (line 2) | function N(e,t){e.onWarning&&e.onWarning.call(null,I(e,t))}
  function L (line 2) | function L(e,t,n,r){var i,o,s,a;if(t<n){if(a=e.input.slice(t,n),r)for(i=...
  function D (line 2) | function D(e,t,n,i){var o,s,l,c;for(r.isObject(n)||R(e,"cannot merge map...
  function M (line 2) | function M(e,t,n,r,i,o,s,l,c){var u,p;if(Array.isArray(i))for(u=0,p=(i=A...
  function F (line 2) | function F(e){var t;10===(t=e.input.charCodeAt(e.position))?e.position++...
  function z (line 2) | function z(e,t,n){for(var r=0,i=e.input.charCodeAt(e.position);0!==i;){f...
  function B (line 2) | function B(e){var t,n=e.position;return!(45!==(t=e.input.charCodeAt(n))&...
  function U (line 2) | function U(e,t){1===t?e.result+=" ":t>1&&(e.result+=r.repeat("\n",t-1))}
  function q (line 2) | function q(e,t){var n,r,i=e.tag,o=e.anchor,s=[],a=!1;if(-1!==e.firstTabI...
  function V (line 2) | function V(e){var t,n,r,i,o=!1,s=!1;if(33!==(i=e.input.charCodeAt(e.posi...
  function W (line 2) | function W(e){var t,n;if(38!==(n=e.input.charCodeAt(e.position)))return!...
  function H (line 2) | function H(e,t,n,i,o){var s,m,g,y,b,v,x,_,P,T=1,I=!1,N=!1;if(null!==e.li...
  function Y (line 2) | function Y(e){var t,n,r,i,o=e.position,s=!1;for(e.version=null,e.checkLi...
  function G (line 2) | function G(e,t){t=t||{},0!==(e=String(e)).length&&(10!==e.charCodeAt(e.l...
  function o (line 2) | function o(e,t){var n=[];return e[t].forEach((function(e){var t=n.length...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e){return this.extend(e)}
  function r (line 2) | function r(e){e.multi?(n.multi[e.kind].push(e),n.multi.fallback.push(e))...
  function i (line 2) | function i(e,t,n,r,i){var o="",s="",a=Math.floor(i/2)-1;return r-t>a&&(t...
  function o (line 2) | function o(e,t){return r.repeat(" ",t-e.length)+e}
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function o (line 2) | function o(e){return 48<=e&&e<=55}
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e){return 48<=e&&e<=57}
  function i (line 2) | function i(e,t,n){if(3===arguments.length)return i.set(e,t,n);if(2===arg...
  function z (line 2) | function z(e,t){for(var n=-1,r=null==e?0:e.length;++n<r;)if(t(e[n],n,e))...
  function B (line 2) | function B(e,t){return e.has(t)}
  function U (line 2) | function U(e){var t=-1,n=Array(e.size);return e.forEach((function(e,r){n...
  function q (line 2) | function q(e){var t=-1,n=Array(e.size);return e.forEach((function(e){n[+...
  function Ee (line 2) | function Ee(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){va...
  function Oe (line 2) | function Oe(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){va...
  function _e (line 2) | function _e(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){va...
  function Ae (line 2) | function Ae(e){var t=-1,n=null==e?0:e.length;for(this.__data__=new _e;++...
  function Ce (line 2) | function Ce(e){var t=this.__data__=new Oe(e);this.size=t.size}
  function je (line 2) | function je(e,t){for(var n=e.length;n--;)if(Be(e[n][0],t))return n;retur...
  function Pe (line 2) | function Pe(e){return null==e?void 0===e?E:y:ae&&ae in Object(e)?functio...
  function Te (line 2) | function Te(e){return Ge(e)&&Pe(e)==a}
  function Ie (line 2) | function Ie(e,t,n,r,s){return e===t||(null==e||null==t||!Ge(e)&&!Ge(t)?e...
  function Re (line 2) | function Re(e,t,n,r,s,a){var l=n&i,c=e.length,u=t.length;if(c!=u&&!(l&&u...
  function Ne (line 2) | function Ne(e){return function(e,t,n){var r=t(e);return qe(e)?r:function...
  function $e (line 2) | function $e(e,t){var n,r,i=e.__data__;return("string"==(r=typeof(n=t))||...
  function Le (line 2) | function Le(e,t){var n=function(e,t){return null==e?void 0:e[t]}(e,t);re...
  function Fe (line 2) | function Fe(e,t){return!!(t=null==t?s:t)&&("number"==typeof e||j.test(e)...
  function ze (line 2) | function ze(e){if(null!=e){try{return K.call(e)}catch(e){}try{return e+"...
  function Be (line 2) | function Be(e,t){return e===t||e!=e&&t!=t}
  function We (line 2) | function We(e){if(!Ye(e))return!1;var t=Pe(e);return t==f||t==h||t==c||t...
  function He (line 2) | function He(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=s}
  function Ye (line 2) | function Ye(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}
  function Ge (line 2) | function Ge(e){return null!=e&&"object"==typeof e}
  function Xe (line 2) | function Xe(e){return null!=(t=e)&&He(t.length)&&!We(t)?function(e,t){va...
  function e (line 2) | function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.en...
  function e (line 2) | function e(n){var r=!(arguments.length>1&&void 0!==arguments[1])||argume...
  function o (line 2) | function o(e){t(this,o),this.ctx=e,this.ie=!1;var n=window.navigator.use...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function o (line 2) | function o(e,t){function n(e,t){return r.stringify(e)===r.stringify(Obje...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e){let t=(e=e.replace("[]","Array")).split("/");return t[0]=t...
  function h (line 2) | function h(e,t,n,r,i,s){let a=s.externalRefs[n+r].paths[0],p=o.parse(i),...
  function m (line 2) | function m(e,t){if(!t.filters||!t.filters.length)return e;for(let n of t...
  function g (line 2) | function g(e,t,n,s){var c=o.parse(n.source),p=n.source.split("\\").join(...
  function y (line 2) | function y(e){return new Promise((function(t,n){(function(e){return new ...
  function b (line 2) | function b(e,t,n){e.resolver.actions.push([]),y(e).then((function(r){var...
  function v (line 2) | function v(e){if(e.cache||(e.cache={}),e.fetch||(e.fetch=s),e.source){le...
    method constructor (line 2) | constructor(e,t){g(e),t||(t={}),this.options=t,this.set=[],this.patter...
    method debug (line 2) | debug(){}
    method make (line 2) | make(){const e=this.pattern,t=this.options;if(!t.nocomment&&"#"===e.ch...
    method parseNegate (line 2) | parseNegate(){if(this.options.nonegate)return;const e=this.pattern;let...
    method matchOne (line 2) | matchOne(e,t,n){var r=this.options;this.debug("matchOne",{this:this,fi...
    method braceExpand (line 2) | braceExpand(){return m(this.pattern,this.options)}
    method parse (line 2) | parse(e,t){g(e);const n=this.options;if("**"===e){if(!n.noglobstar)ret...
    method makeRe (line 2) | makeRe(){if(this.regexp||!1===this.regexp)return this.regexp;const e=t...
    method match (line 2) | match(e,t=this.partial){if(this.debug("match",e,this.pattern),this.com...
    method defaults (line 2) | static defaults(e){return r.defaults(e).Minimatch}
  function t (line 2) | function t(){return{depth:0,seen:new WeakMap,top:!0,combine:!1,allowRefS...
  function t (line 2) | function t(e){if("string"!=typeof e)throw new TypeError("Path must be a ...
  function n (line 2) | function n(e,t){for(var n,r="",i=0,o=-1,s=0,a=0;a<=e.length;++a){if(a<e....
  function o (line 2) | function o(e){return"string"==typeof e?new RegExp("^"+e+"$","i"):e}
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e,t){return e===t?t:e===e.toLowerCase()?t.toLowerCase():e===e...
  function a (line 2) | function a(e,t){return e.replace(t[0],(function(n,r){var i,o,a=(i=t[1],o...
  function l (line 2) | function l(e,t,r){if(!e.length||n.hasOwnProperty(e))return t;for(var i=r...
  function c (line 2) | function c(e,t,n){return function(r){var i=r.toLowerCase();return t.hasO...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function u (line 2) | function u(e,t,n,r){return function(r){var i=r.toLowerCase();return!!t.h...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  function p (line 2) | function p(e,t,n){return(n?t+" ":"")+(1===t?p.singular(e):p.plural(e))}
    method constructor (line 2) | constructor(e,n){this.rawConfig=e,this.configFile=n,this.ignore={},thi...
    method resolveIgnore (line 2) | resolveIgnore(e){if(e&&(0,s.doesYamlFileExist)(e)){this.ignore=(0,o.pa...
    method saveIgnore (line 2) | saveIgnore(){const e=this.configFile?i.dirname(this.configFile):proces...
    method addIgnore (line 2) | addIgnore(e){const t=this.ignore,n=e.location[0];if(void 0===n.pointer...
    method addProblemToIgnore (line 2) | addProblemToIgnore(e){const t=e.location[0];if(void 0===t.pointer)retu...
    method extendTypes (line 2) | extendTypes(e,t){let n=e;for(const e of this.plugins)if(void 0!==e.typ...
    method getRuleSettings (line 2) | getRuleSettings(e,t){this._usedRules.add(e),this._usedVersions.add(t);...
    method getPreprocessorSettings (line 2) | getPreprocessorSettings(e,t){this._usedRules.add(e),this._usedVersions...
    method getDecoratorSettings (line 2) | getDecoratorSettings(e,t){this._usedRules.add(e),this._usedVersions.ad...
    method getUnusedRules (line 2) | getUnusedRules(){const e=[],t=[],n=[];for(const r of Array.from(this._...
    method getRulesForOasVersion (line 2) | getRulesForOasVersion(e){switch(e){case a.SpecMajorVersion.OAS3:const ...
    method skipRules (line 2) | skipRules(e){for(const t of e||[])for(const e of Object.values(a.SpecV...
    method skipPreprocessors (line 2) | skipPreprocessors(e){for(const t of e||[])for(const e of Object.values...
    method skipDecorators (line 2) | skipDecorators(e){for(const t of e||[])for(const e of Object.values(a....
  function t (line 2) | function t(e,t){return e.replace(/<<(\d+)>>/g,(function(e,n){return"(?:"...
  function n (line 2) | function n(e,n,r){return RegExp(t(e,n),r||"")}
  function r (line 2) | function r(e,t){for(var n=0;n<t;n++)e=e.replace(/<<self>>/g,(function(){...
  function l (line 2) | function l(e){return"\\b(?:"+e.trim().replace(/ /g,"|")+")\\b"}
  function D (line 2) | function D(t,r){return{interpolation:{pattern:n(/((?:^|[^{])(?:\{\{)*)<<...
  function t (line 2) | function t(e){return RegExp("(^(?:"+e+"):[ \t]*(?![ \t]))[^]+","i")}
  function s (line 2) | function s(e){var t=e.replace(/^[a-z]+\//,"");return"(?:"+e+"|\\w+/(?:[\...
  function t (line 2) | function t(e,t){return"___"+e.toUpperCase()+t+"___"}
  function s (line 2) | function s(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<...
  function c (line 2) | function c(e){l.highlightedCode=e,i.hooks.run("before-insert",l),l.eleme...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function o (line 2) | function o(e,t,n,r){this.type=e,this.content=t,this.alias=n,this.length=...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e,t,n,r){e.lastIndex=t;var i=e.exec(n);if(i&&r&&i[1]){var o=i...
  function a (line 2) | function a(e,t,n,r,l,p){for(var d in n)if(n.hasOwnProperty(d)&&n[d]){var...
  function l (line 2) | function l(){var e={value:null,prev:null,next:null},t={value:null,prev:e...
  function c (line 2) | function c(e,t,n){var r=t.next,i={value:n,prev:t,next:r};return t.next=i...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function u (line 2) | function u(e,t,n){for(var r=t.next,i=0;i<n&&r!==e.tail;i++)r=r.next;t.ne...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  function d (line 2) | function d(){i.manual||i.highlightAll()}
    method constructor (line 2) | constructor(e,t){super(e.message.split("\n")[0]),this.originalError=e,...
  function i (line 2) | function i(){}
  function o (line 2) | function o(){}
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function e (line 2) | function e(e,t,n,i,o,s){if(s!==r){var a=new Error("Calling PropTypes val...
  function t (line 2) | function t(){return e}
  function o (line 2) | function o(e){for(var t="https://reactjs.org/docs/error-decoder.html?inv...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function l (line 2) | function l(e,t){c(e,t),c(e+"Capture",t)}
  function c (line 2) | function c(e,t){for(a[e]=t,e=0;e<t.length;e++)s.add(t[e])}
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function m (line 2) | function m(e,t,n,r,i,o,s){this.acceptsBooleans=2===t||3===t||4===t,this....
  function b (line 2) | function b(e){return e[1].toUpperCase()}
  function v (line 2) | function v(e,t,n,r){var i=g.hasOwnProperty(t)?g[t]:null;(null!==i?0!==i....
    method constructor (line 2) | constructor(e,t){g(e),t||(t={}),this.options=t,this.set=[],this.patter...
    method debug (line 2) | debug(){}
    method make (line 2) | make(){const e=this.pattern,t=this.options;if(!t.nocomment&&"#"===e.ch...
    method parseNegate (line 2) | parseNegate(){if(this.options.nonegate)return;const e=this.pattern;let...
    method matchOne (line 2) | matchOne(e,t,n){var r=this.options;this.debug("matchOne",{this:this,fi...
    method braceExpand (line 2) | braceExpand(){return m(this.pattern,this.options)}
    method parse (line 2) | parse(e,t){g(e);const n=this.options;if("**"===e){if(!n.noglobstar)ret...
    method makeRe (line 2) | makeRe(){if(this.regexp||!1===this.regexp)return this.regexp;const e=t...
    method match (line 2) | match(e,t=this.partial){if(this.debug("match",e,this.pattern),this.com...
    method defaults (line 2) | static defaults(e){return r.defaults(e).Minimatch}
  function $ (line 2) | function $(e){return null===e||"object"!=typeof e?null:"function"==typeo...
  function M (line 2) | function M(e){if(void 0===L)try{throw Error()}catch(e){var t=e.stack.tri...
  function z (line 2) | function z(e,t){if(!e||F)return"";F=!0;var n=Error.prepareStackTrace;Err...
  function B (line 2) | function B(e){switch(e.tag){case 5:return M(e.type);case 16:return M("La...
  function U (line 2) | function U(e){if(null==e)return null;if("function"==typeof e)return e.di...
  function q (line 2) | function q(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:re...
  function V (line 2) | function V(e){switch(typeof e){case"boolean":case"number":case"string":c...
  function W (line 2) | function W(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase...
  function H (line 2) | function H(e){e._valueTracker||(e._valueTracker=function(e){var t=W(e)?"...
  function Y (line 2) | function Y(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=...
  function G (line 2) | function G(e){if(void 0===(e=e||("undefined"!=typeof document?document:v...
  function Q (line 2) | function Q(e,t){var n=t.checked;return D({},t,{defaultChecked:void 0,def...
  function X (line 2) | function X(e,t){var n=null==t.defaultValue?"":t.defaultValue,r=null!=t.c...
  function K (line 2) | function K(e,t){null!=(t=t.checked)&&v(e,"checked",t,!1)}
  function Z (line 2) | function Z(e,t){K(e,t);var n=V(t.value),r=t.type;if(null!=n)"number"===r...
  function J (line 2) | function J(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaul...
  function ee (line 2) | function ee(e,t,n){"number"===t&&G(e.ownerDocument)===e||(null==n?e.defa...
  function ne (line 2) | function ne(e,t,n,r){if(e=e.options,t){t={};for(var i=0;i<n.length;i++)t...
  function re (line 2) | function re(e,t){if(null!=t.dangerouslySetInnerHTML)throw Error(o(91));r...
  function ie (line 2) | function ie(e,t){var n=t.value;if(null==n){if(n=t.children,t=t.defaultVa...
  function oe (line 2) | function oe(e,t){var n=V(t.value),r=V(t.defaultValue);null!=n&&((n=""+n)...
  function se (line 2) | function se(e){var t=e.textContent;t===e._wrapperState.initialValue&&""!...
  function ae (line 2) | function ae(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";ca...
  function le (line 2) | function le(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?ae(t...
  function de (line 2) | function de(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.n...
  function me (line 2) | function me(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"nu...
  function ge (line 2) | function ge(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var r=...
  function be (line 2) | function be(e,t){if(t){if(ye[e]&&(null!=t.children||null!=t.dangerouslyS...
  function ve (line 2) | function ve(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;swit...
  function we (line 2) | function we(e){return(e=e.target||e.srcElement||window).correspondingUse...
  function Oe (line 2) | function Oe(e){if(e=vi(e)){if("function"!=typeof ke)throw Error(o(280));...
  function _e (line 2) | function _e(e){Se?Ee?Ee.push(e):Ee=[e]:Se=e}
  function Ae (line 2) | function Ae(){if(Se){var e=Se,t=Ee;if(Ee=Se=null,Oe(e),t)for(e=0;e<t.len...
  function Ce (line 2) | function Ce(e,t){return e(t)}
  function je (line 2) | function je(){}
  function Te (line 2) | function Te(e,t,n){if(Pe)return e(t,n);Pe=!0;try{return Ce(e,t,n)}finall...
  function Ie (line 2) | function Ie(e,t){var n=e.stateNode;if(null===n)return null;var r=wi(n);i...
  function $e (line 2) | function $e(e,t,n,r,i,o,s,a,l){var c=Array.prototype.slice.call(argument...
  function Be (line 2) | function Be(e,t,n,r,i,o,s,a,l){Le=!1,De=null,$e.apply(ze,arguments)}
  function Ue (line 2) | function Ue(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else...
  function qe (line 2) | function qe(e){if(13===e.tag){var t=e.memoizedState;if(null===t&&null!==...
  function Ve (line 2) | function Ve(e){if(Ue(e)!==e)throw Error(o(188))}
  function We (line 2) | function We(e){return null!==(e=function(e){var t=e.alternate;if(!t){if(...
  function He (line 2) | function He(e){if(5===e.tag||6===e.tag)return e;for(e=e.child;null!==e;)...
  function pt (line 2) | function pt(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:retur...
  function dt (line 2) | function dt(e,t){var n=e.pendingLanes;if(0===n)return 0;var r=0,i=e.susp...
  function ft (line 2) | function ft(e,t){switch(e){case 1:case 2:case 4:return t+250;case 8:case...
  function ht (line 2) | function ht(e){return 0!=(e=-1073741825&e.pendingLanes)?e:1073741824&e?1...
  function mt (line 2) | function mt(){var e=ct;return!(4194240&(ct<<=1))&&(ct=64),e}
  function gt (line 2) | function gt(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}
  function yt (line 2) | function yt(e,t,n){e.pendingLanes|=t,536870912!==t&&(e.suspendedLanes=0,...
  function bt (line 2) | function bt(e,t){var n=e.entangledLanes|=t;for(e=e.entanglements;n;){var...
  function xt (line 2) | function xt(e){return 1<(e&=-e)?4<e?268435455&e?16:536870912:4:1}
  function $t (line 2) | function $t(e,t){switch(e){case"focusin":case"focusout":Ct=null;break;ca...
  function Lt (line 2) | function Lt(e,t,n,r,i,o){return null===e||e.nativeEvent!==o?(e={blockedO...
  function Dt (line 2) | function Dt(e){var t=bi(e.target);if(null!==t){var n=Ue(t);if(null!==n)i...
  function Mt (line 2) | function Mt(e){if(null!==e.blockedOn)return!1;for(var t=e.targetContaine...
  function Ft (line 2) | function Ft(e,t,n){Mt(e)&&n.delete(t)}
  function zt (line 2) | function zt(){_t=!1,null!==Ct&&Mt(Ct)&&(Ct=null),null!==jt&&Mt(jt)&&(jt=...
  function Bt (line 2) | function Bt(e,t){e.blockedOn===t&&(e.blockedOn=null,_t||(_t=!0,i.unstabl...
  function Ut (line 2) | function Ut(e){function t(t){return Bt(t,e)}if(0<At.length){Bt(At[0],e);...
  function Wt (line 2) | function Wt(e,t,n,r){var i=vt,o=qt.transition;qt.transition=null;try{vt=...
  function Ht (line 2) | function Ht(e,t,n,r){var i=vt,o=qt.transition;qt.transition=null;try{vt=...
  function Yt (line 2) | function Yt(e,t,n,r){if(Vt){var i=Qt(e,t,n,r);if(null===i)Vr(e,t,r,Gt,n)...
  function Qt (line 2) | function Qt(e,t,n,r){if(Gt=null,null!==(e=bi(e=we(r))))if(null===(t=Ue(e...
  function Xt (line 2) | function Xt(e){switch(e){case"cancel":case"click":case"close":case"conte...
  function en (line 2) | function en(){if(Jt)return Jt;var e,t,n=Zt,r=n.length,i="value"in Kt?Kt....
  function tn (line 2) | function tn(e){var t=e.keyCode;return"charCode"in e?0===(e=e.charCode)&&...
  function nn (line 2) | function nn(){return!0}
  function rn (line 2) | function rn(){return!1}
  function on (line 2) | function on(e){function t(t,n,r,i,o){for(var s in this._reactName=t,this...
  function En (line 2) | function En(e){var t=this.nativeEvent;return t.getModifierState?t.getMod...
  function On (line 2) | function On(){return En}
  function zn (line 2) | function zn(e,t){switch(e){case"keyup":return-1!==Rn.indexOf(t.keyCode);...
  function Bn (line 2) | function Bn(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}
  function Vn (line 2) | function Vn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"inpu...
  function Wn (line 2) | function Wn(e,t,n,r){_e(r),0<(t=Hr(t,"onChange")).length&&(n=new un("onC...
  function Gn (line 2) | function Gn(e){Mr(e,0)}
  function Qn (line 2) | function Qn(e){if(Y(xi(e)))return e}
  function Xn (line 2) | function Xn(e,t){if("change"===e)return t}
  function tr (line 2) | function tr(){Hn&&(Hn.detachEvent("onpropertychange",nr),Yn=Hn=null)}
  function nr (line 2) | function nr(e){if("value"===e.propertyName&&Qn(Yn)){var t=[];Wn(t,Yn,e,w...
  function rr (line 2) | function rr(e,t,n){"focusin"===e?(tr(),Yn=n,(Hn=t).attachEvent("onproper...
  function ir (line 2) | function ir(e){if("selectionchange"===e||"keyup"===e||"keydown"===e)retu...
  function or (line 2) | function or(e,t){if("click"===e)return Qn(t)}
  function sr (line 2) | function sr(e,t){if("input"===e||"change"===e)return Qn(t)}
  function lr (line 2) | function lr(e,t){if(ar(e,t))return!0;if("object"!=typeof e||null===e||"o...
  function cr (line 2) | function cr(e){for(;e&&e.firstChild;)e=e.firstChild;return e}
  function ur (line 2) | function ur(e,t){var n,r=cr(e);for(e=0;r;){if(3===r.nodeType){if(n=e+r.t...
  function pr (line 2) | function pr(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===...
  function dr (line 2) | function dr(){for(var e=window,t=G();t instanceof e.HTMLIFrameElement;){...
  function fr (line 2) | function fr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(...
  function hr (line 2) | function hr(e){var t=dr(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n...
  function xr (line 2) | function xr(e,t,n){var r=n.window===n?n.document:9===n.nodeType?n:n.owne...
  function wr (line 2) | function wr(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["W...
  function Or (line 2) | function Or(e){if(Sr[e])return Sr[e];if(!kr[e])return e;var t,n=kr[e];fo...
  function Ir (line 2) | function Ir(e,t){Pr.set(e,t),l(t,[e])}
  function Dr (line 2) | function Dr(e,t,n){var r=e.type||"unknown-event";e.currentTarget=n,funct...
  function Mr (line 2) | function Mr(e,t){t=!!(4&t);for(var n=0;n<e.length;n++){var r=e[n],i=r.ev...
  function Fr (line 2) | function Fr(e,t){var n=t[mi];void 0===n&&(n=t[mi]=new Set);var r=e+"__bu...
  function zr (line 2) | function zr(e,t,n){var r=0;t&&(r|=4),qr(n,e,r,t)}
  function Ur (line 2) | function Ur(e){if(!e[Br]){e[Br]=!0,s.forEach((function(t){"selectionchan...
  function qr (line 2) | function qr(e,t,n,r){switch(Xt(t)){case 1:var i=Wt;break;case 4:i=Ht;bre...
  function Vr (line 2) | function Vr(e,t,n,r,i){var o=r;if(!(1&t||2&t||null===r))e:for(;;){if(nul...
  function Wr (line 2) | function Wr(e,t,n){return{instance:e,listener:t,currentTarget:n}}
  function Hr (line 2) | function Hr(e,t){for(var n=t+"Capture",r=[];null!==e;){var i=e,o=i.state...
  function Yr (line 2) | function Yr(e){if(null===e)return null;do{e=e.return}while(e&&5!==e.tag)...
  function Gr (line 2) | function Gr(e,t,n,r,i){for(var o=t._reactName,s=[];null!==n&&n!==r;){var...
  function Kr (line 2) | function Kr(e){return("string"==typeof e?e:""+e).replace(Qr,"\n").replac...
  function Zr (line 2) | function Zr(e,t,n){if(t=Kr(t),Kr(e)!==t&&n)throw Error(o(425))}
  function Jr (line 2) | function Jr(){}
  function ni (line 2) | function ni(e,t){return"textarea"===e||"noscript"===e||"string"==typeof ...
  function ai (line 2) | function ai(e){setTimeout((function(){throw e}))}
  function li (line 2) | function li(e,t){var n=t,r=0;do{var i=n.nextSibling;if(e.removeChild(n),...
  function ci (line 2) | function ci(e){for(;null!=e;e=e.nextSibling){var t=e.nodeType;if(1===t||...
  function ui (line 2) | function ui(e){e=e.previousSibling;for(var t=0;e;){if(8===e.nodeType){va...
  function bi (line 2) | function bi(e){var t=e[di];if(t)return t;for(var n=e.parentNode;n;){if(t...
  function vi (line 2) | function vi(e){return!(e=e[di]||e[hi])||5!==e.tag&&6!==e.tag&&13!==e.tag...
  function xi (line 2) | function xi(e){if(5===e.tag||6===e.tag)return e.stateNode;throw Error(o(...
  function wi (line 2) | function wi(e){return e[fi]||null}
  function Ei (line 2) | function Ei(e){return{current:e}}
  function Oi (line 2) | function Oi(e){0>Si||(e.current=ki[Si],ki[Si]=null,Si--)}
  function _i (line 2) | function _i(e,t){Si++,ki[Si]=e.current,e.current=t}
  function Ti (line 2) | function Ti(e,t){var n=e.type.contextTypes;if(!n)return Ai;var r=e.state...
  function Ii (line 2) | function Ii(e){return null!=e.childContextTypes}
  function Ri (line 2) | function Ri(){Oi(ji),Oi(Ci)}
  function Ni (line 2) | function Ni(e,t,n){if(Ci.current!==Ai)throw Error(o(168));_i(Ci,t),_i(ji...
  function $i (line 2) | function $i(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,"function"...
  function Li (line 2) | function Li(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMerged...
  function Di (line 2) | function Di(e,t,n){var r=e.stateNode;if(!r)throw Error(o(169));n?(e=$i(e...
  function Bi (line 2) | function Bi(e){null===Mi?Mi=[e]:Mi.push(e)}
  function Ui (line 2) | function Ui(){if(!zi&&null!==Mi){zi=!0;var e=0,t=vt;try{var n=Mi;for(vt=...
  function Zi (line 2) | function Zi(e,t){qi[Vi++]=Hi,qi[Vi++]=Wi,Wi=e,Hi=t}
  function Ji (line 2) | function Ji(e,t,n){Yi[Gi++]=Xi,Yi[Gi++]=Ki,Yi[Gi++]=Qi,Qi=e;var r=Xi;e=K...
  function eo (line 2) | function eo(e){null!==e.return&&(Zi(e,1),Ji(e,1,0))}
  function to (line 2) | function to(e){for(;e===Wi;)Wi=qi[--Vi],qi[Vi]=null,Hi=qi[--Vi],qi[Vi]=n...
  function so (line 2) | function so(e,t){var n=Tc(5,null,null,0);n.elementType="DELETED",n.state...
  function ao (line 2) | function ao(e,t){switch(e.tag){case 5:var n=e.type;return null!==(t=1!==...
  function lo (line 2) | function lo(e){return!(!(1&e.mode)||128&e.flags)}
  function co (line 2) | function co(e){if(io){var t=ro;if(t){var n=t;if(!ao(e,t)){if(lo(e))throw...
  function uo (line 2) | function uo(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag&&13!==e.tag...
  function po (line 2) | function po(e){if(e!==no)return!1;if(!io)return uo(e),io=!0,!1;var t;if(...
  function fo (line 2) | function fo(){for(var e=ro;e;)e=ci(e.nextSibling)}
  function ho (line 2) | function ho(){ro=no=null,io=!1}
  function mo (line 2) | function mo(e){null===oo?oo=[e]:oo.push(e)}
  function yo (line 2) | function yo(e,t,n){if(null!==(e=n.ref)&&"function"!=typeof e&&"object"!=...
  function bo (line 2) | function bo(e,t){throw e=Object.prototype.toString.call(t),Error(o(31,"[...
  function vo (line 2) | function vo(e){return(0,e._init)(e._payload)}
  function xo (line 2) | function xo(e){function t(t,n){if(e){var r=t.deletions;null===r?(t.delet...
  function Ao (line 2) | function Ao(){_o=Oo=Eo=null}
  function Co (line 2) | function Co(e){var t=So.current;Oi(So),e._currentValue=t}
  function jo (line 2) | function jo(e,t,n){for(;null!==e;){var r=e.alternate;if((e.childLanes&t)...
  function Po (line 2) | function Po(e,t){Eo=e,_o=Oo=null,null!==(e=e.dependencies)&&null!==e.fir...
  function To (line 2) | function To(e){var t=e._currentValue;if(_o!==e)if(e={context:e,memoizedV...
  function Ro (line 2) | function Ro(e){null===Io?Io=[e]:Io.push(e)}
  function No (line 2) | function No(e,t,n,r){var i=t.interleaved;return null===i?(n.next=n,Ro(t)...
  function $o (line 2) | function $o(e,t){e.lanes|=t;var n=e.alternate;for(null!==n&&(n.lanes|=t)...
  function Do (line 2) | function Do(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:...
  function Mo (line 2) | function Mo(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={base...
  function Fo (line 2) | function Fo(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:n...
  function zo (line 2) | function zo(e,t,n){var r=e.updateQueue;if(null===r)return null;if(r=r.sh...
  function Bo (line 2) | function Bo(e,t,n){if(null!==(t=t.updateQueue)&&(t=t.shared,4194240&n)){...
  function Uo (line 2) | function Uo(e,t){var n=e.updateQueue,r=e.alternate;if(null!==r&&n===(r=r...
  function qo (line 2) | function qo(e,t,n,r){var i=e.updateQueue;Lo=!1;var o=i.firstBaseUpdate,s...
  function Vo (line 2) | function Vo(e,t,n){if(e=t.effects,t.effects=null,null!==e)for(t=0;t<e.le...
  function Qo (line 2) | function Qo(e){if(e===Wo)throw Error(o(174));return e}
  function Xo (line 2) | function Xo(e,t){switch(_i(Go,t),_i(Yo,e),_i(Ho,Wo),e=t.nodeType){case 9...
  function Ko (line 2) | function Ko(){Oi(Ho),Oi(Yo),Oi(Go)}
  function Zo (line 2) | function Zo(e){Qo(Go.current);var t=Qo(Ho.current),n=le(t,e.type);t!==n&...
  function Jo (line 2) | function Jo(e){Yo.current===e&&(Oi(Ho),Oi(Yo))}
  function ts (line 2) | function ts(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedSta...
  function rs (line 2) | function rs(){for(var e=0;e<ns.length;e++)ns[e]._workInProgressVersionPr...
  function hs (line 2) | function hs(){throw Error(o(321))}
  function ms (line 2) | function ms(e,t){if(null===t)return!1;for(var n=0;n<t.length&&n<e.length...
  function gs (line 2) | function gs(e,t,n,r,i,s){if(ss=s,as=t,t.memoizedState=null,t.updateQueue...
  function ys (line 2) | function ys(){var e=0!==ds;return ds=0,e}
  function bs (line 2) | function bs(){var e={memoizedState:null,baseState:null,baseQueue:null,qu...
  function vs (line 2) | function vs(){if(null===ls){var e=as.alternate;e=null!==e?e.memoizedStat...
  function xs (line 2) | function xs(e,t){return"function"==typeof t?t(e):t}
  function ws (line 2) | function ws(e){var t=vs(),n=t.queue;if(null===n)throw Error(o(311));n.la...
  function ks (line 2) | function ks(e){var t=vs(),n=t.queue;if(null===n)throw Error(o(311));n.la...
  function Ss (line 2) | function Ss(){}
    method constructor (line 17) | constructor(e){super(e),this.state={error:void 0}}
    method componentDidCatch (line 17) | componentDidCatch(e){return this.setState({error:e}),!1}
    method render (line 17) | render(){return this.state.error?n.createElement(ks,null,n.createEleme...
  function Es (line 2) | function Es(e,t){var n=as,r=vs(),i=t(),s=!ar(r.memoizedState,i);if(s&&(r...
  function Os (line 2) | function Os(e,t,n){e.flags|=16384,e={getSnapshot:t,value:n},null===(t=as...
  function _s (line 2) | function _s(e,t,n,r){t.value=n,t.getSnapshot=r,Cs(t)&&js(e)}
  function As (line 2) | function As(e,t,n){return n((function(){Cs(t)&&js(e)}))}
    method render (line 41) | render(){return n.createElement("div",{style:{textAlign:"center"}},n.c...
  function Cs (line 2) | function Cs(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!ar(e,n...
  function js (line 2) | function js(e){var t=$o(e,1);null!==t&&nc(t,e,1,-1)}
  function Ps (line 2) | function Ps(e){var t=bs();return"function"==typeof e&&(e=e()),t.memoized...
  function Ts (line 2) | function Ts(e,t,n,r){return e={tag:e,create:t,destroy:n,deps:r,next:null...
  function Is (line 2) | function Is(){return vs().memoizedState}
  function Rs (line 2) | function Rs(e,t,n,r){var i=bs();as.flags|=e,i.memoizedState=Ts(1|t,n,voi...
  function Ns (line 2) | function Ns(e,t,n,r){var i=vs();r=void 0===r?null:r;var o=void 0;if(null...
  function $s (line 2) | function $s(e,t){return Rs(8390656,8,e,t)}
  function Ls (line 2) | function Ls(e,t){return Ns(2048,8,e,t)}
  function Ds (line 2) | function Ds(e,t){return Ns(4,2,e,t)}
  function Ms (line 2) | function Ms(e,t){return Ns(4,4,e,t)}
  function Fs (line 2) | function Fs(e,t){return"function"==typeof t?(e=e(),t(e),function(){t(nul...
  function zs (line 2) | function zs(e,t,n){return n=null!=n?n.concat([e]):null,Ns(4,4,Fs.bind(nu...
  function Bs (line 2) | function Bs(){}
    method baseName (line 41) | static baseName(e,t=1){const n=Bs.parse(e);return n[n.length-t]}
    method dirName (line 41) | static dirName(e,t=1){const n=Bs.parse(e);return Ms.compile(n.slice(0,...
    method relative (line 41) | static relative(e,t){const n=Bs.parse(e);return Bs.parse(t).slice(n.le...
    method parse (line 41) | static parse(e){let t=e;return"#"===t.charAt(0)&&(t=t.substring(1)),zs...
    method join (line 41) | static join(e,t){const n=Bs.parse(e).concat(t);return Ms.compile(n)}
    method get (line 41) | static get(e,t){return Ms.get(e,t)}
    method compile (line 41) | static compile(e){return Ms.compile(e)}
    method escape (line 41) | static escape(e){return Ms.escape(e)}
  function Us (line 2) | function Us(e,t){var n=vs();t=void 0===t?null:t;var r=n.memoizedState;re...
  function qs (line 2) | function qs(e,t){var n=vs();t=void 0===t?null:t;var r=n.memoizedState;re...
  function Vs (line 2) | function Vs(e,t,n){return 21&ss?(ar(n,t)||(n=mt(),as.lanes|=n,Ll|=n,e.ba...
  function Ws (line 2) | function Ws(e,t){var n=vt;vt=0!==n&&4>n?n:4,e(!0);var r=os.transition;os...
  function Hs (line 2) | function Hs(){return vs().memoizedState}
  function Ys (line 2) | function Ys(e,t,n){var r=tc(e);n={lane:r,action:n,hasEagerState:!1,eager...
  function Gs (line 2) | function Gs(e,t,n){var r=tc(e),i={lane:r,action:n,hasEagerState:!1,eager...
  function Qs (line 2) | function Qs(e){var t=e.alternate;return e===as||null!==t&&t===as}
  function Xs (line 2) | function Xs(e,t){ps=us=!0;var n=e.pending;null===n?t.next=t:(t.next=n.ne...
  function Ks (line 2) | function Ks(e,t,n){if(4194240&n){var r=t.lanes;n|=r&=e.pendingLanes,t.la...
  function na (line 2) | function na(e,t){if(e&&e.defaultProps){for(var n in t=D({},t),e=e.defaul...
  function ra (line 2) | function ra(e,t,n,r){n=null==(n=n(r,t=e.memoizedState))?t:D({},t,n),e.me...
  function oa (line 2) | function oa(e,t,n,r,i,o,s){return"function"==typeof(e=e.stateNode).shoul...
  function sa (line 2) | function sa(e,t,n){var r=!1,i=Ai,o=t.contextType;return"object"==typeof ...
  function aa (line 2) | function aa(e,t,n,r){e=t.state,"function"==typeof t.componentWillReceive...
  function la (line 2) | function la(e,t,n,r){var i=e.stateNode;i.props=n,i.state=e.memoizedState...
  function ca (line 2) | function ca(e,t){try{var n="",r=t;do{n+=B(r),r=r.return}while(r);var i=n...
  function ua (line 2) | function ua(e,t,n){return{value:e,source:null,stack:null!=n?n:null,diges...
  function pa (line 2) | function pa(e,t){try{console.error(t.value)}catch(e){setTimeout((functio...
  function fa (line 2) | function fa(e,t,n){(n=Fo(-1,n)).tag=3,n.payload={element:null};var r=t.v...
  function ha (line 2) | function ha(e,t,n){(n=Fo(-1,n)).tag=3;var r=e.type.getDerivedStateFromEr...
  function ma (line 2) | function ma(e,t,n){var r=e.pingCache;if(null===r){r=e.pingCache=new da;v...
  function ga (line 2) | function ga(e){do{var t;if((t=13===e.tag)&&(t=null===(t=e.memoizedState)...
  function ya (line 2) | function ya(e,t,n,r,i){return 1&e.mode?(e.flags|=65536,e.lanes=i,e):(e==...
  function xa (line 2) | function xa(e,t,n,r){t.child=null===e?ko(t,null,n,r):wo(t,e.child,n,r)}
  function wa (line 2) | function wa(e,t,n,r,i){n=n.render;var o=t.ref;return Po(t,i),r=gs(e,t,n,...
  function ka (line 2) | function ka(e,t,n,r,i){if(null===e){var o=n.type;return"function"!=typeo...
  function Sa (line 2) | function Sa(e,t,n,r,i){if(null!==e){var o=e.memoizedProps;if(lr(o,r)&&e....
  function Ea (line 2) | function Ea(e,t,n){var r=t.pendingProps,i=r.children,o=null!==e?e.memoiz...
  function Oa (line 2) | function Oa(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&...
  function _a (line 2) | function _a(e,t,n,r,i){var o=Ii(n)?Pi:Ci.current;return o=Ti(t,o),Po(t,i...
  function Aa (line 2) | function Aa(e,t,n,r,i){if(Ii(n)){var o=!0;Li(t)}else o=!1;if(Po(t,i),nul...
  function Ca (line 2) | function Ca(e,t,n,r,i,o){Oa(e,t);var s=!!(128&t.flags);if(!r&&!s)return ...
  function ja (line 2) | function ja(e){var t=e.stateNode;t.pendingContext?Ni(0,t.pendingContext,...
  function Pa (line 2) | function Pa(e,t,n,r,i){return ho(),mo(i),t.flags|=256,xa(e,t,n,r),t.child}
  function La (line 2) | function La(e){return{baseLanes:e,cachePool:null,transitions:null}}
  function Da (line 2) | function Da(e,t,n){var r,i=t.pendingProps,s=es.current,a=!1,l=!!(128&t.f...
  function Ma (line 2) | function Ma(e,t){return(t=Lc({mode:"visible",children:t},e.mode,0,null))...
  function Fa (line 2) | function Fa(e,t,n,r){return null!==r&&mo(r),wo(t,e.child,null,n),(e=Ma(t...
  function za (line 2) | function za(e,t,n){e.lanes|=t;var r=e.alternate;null!==r&&(r.lanes|=t),j...
  function Ba (line 2) | function Ba(e,t,n,r,i){var o=e.memoizedState;null===o?e.memoizedState={i...
  function Ua (line 2) | function Ua(e,t,n){var r=t.pendingProps,i=r.revealOrder,o=r.tail;if(xa(e...
  function qa (line 2) | function qa(e,t){!(1&t.mode)&&null!==e&&(e.alternate=null,t.alternate=nu...
    method constructor (line 41) | constructor(){this.emit=()=>{this._emiter.emit(Ua,this.currentId)},thi...
    method currentId (line 41) | get currentId(){return ei?decodeURIComponent(window.location.hash.subs...
    method linkForId (line 41) | linkForId(e){return e?"#"+e:""}
    method subscribe (line 41) | subscribe(e){const t=this._emiter.addListener(Ua,e);return()=>t.remove...
    method bind (line 41) | bind(){ei&&window.addEventListener("hashchange",this.emit,!1)}
    method dispose (line 41) | dispose(){ei&&window.removeEventListener("hashchange",this.emit)}
    method replace (line 41) | replace(e,t=!1){ei&&null!=e&&e!==this.currentId&&(t?window.history.rep...
  function Va (line 2) | function Va(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),Ll|=t.la...
  function Wa (line 2) | function Wa(e,t){if(!io)switch(e.tailMode){case"hidden":t=e.tail;for(var...
  function Ha (line 2) | function Ha(e){var t=null!==e.alternate&&e.alternate.child===e.child,n=0...
    method constructor (line 41) | constructor(){this.map=new Map,this.prevTerm=""}
    method add (line 41) | add(e){this.map.set(e,new Wa(e))}
    method delete (line 41) | delete(e){this.map.delete(e)}
    method addOnly (line 41) | addOnly(e){this.map.forEach(((t,n)=>{-1===e.indexOf(n)&&(t.unmark(),th...
    method clearAll (line 41) | clearAll(){this.unmark(),this.map.clear()}
    method mark (line 41) | mark(e){(e||this.prevTerm)&&(this.map.forEach((t=>{t.unmark(),t.mark(e...
    method unmark (line 41) | unmark(){this.map.forEach((e=>e.unmark())),this.prevTerm=""}
  function Ya (line 2) | function Ya(e,t,n){var r=t.pendingProps;switch(to(t),t.tag){case 2:case ...
  function Ga (line 2) | function Ga(e,t){switch(to(t),t.tag){case 1:return Ii(t.type)&&Ri(),6553...
  function Ja (line 2) | function Ja(e,t){var n=e.ref;if(null!==n)if("function"==typeof n)try{n(n...
  function el (line 2) | function el(e,t,n){try{n()}catch(n){Ec(e,t,n)}}
  function nl (line 2) | function nl(e,t,n){var r=t.updateQueue;if(null!==(r=null!==r?r.lastEffec...
  function rl (line 2) | function rl(e,t){if(null!==(t=null!==(t=t.updateQueue)?t.lastEffect:null...
  function il (line 2) | function il(e){var t=e.ref;if(null!==t){var n=e.stateNode;e.tag,e=n,"fun...
  function ol (line 2) | function ol(e){var t=e.alternate;null!==t&&(e.alternate=null,ol(t)),e.ch...
  function sl (line 2) | function sl(e){return 5===e.tag||3===e.tag||4===e.tag}
  function al (line 2) | function al(e){e:for(;;){for(;null===e.sibling;){if(null===e.return||sl(...
  function ll (line 2) | function ll(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?8===n.nod...
  function cl (line 2) | function cl(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?n.insertB...
  function dl (line 2) | function dl(e,t,n){for(n=n.child;null!==n;)fl(e,t,n),n=n.sibling}
  function fl (line 2) | function fl(e,t,n){if(ot&&"function"==typeof ot.onCommitFiberUnmount)try...
  function hl (line 2) | function hl(e){var t=e.updateQueue;if(null!==t){e.updateQueue=null;var n...
  function ml (line 2) | function ml(e,t){var n=t.deletions;if(null!==n)for(var r=0;r<n.length;r+...
  function gl (line 2) | function gl(e,t){var n=e.alternate,r=e.flags;switch(e.tag){case 0:case 1...
  function yl (line 2) | function yl(e){var t=e.flags;if(2&t){try{e:{for(var n=e.return;null!==n;...
    method constructor (line 41) | constructor(e){this.options=e||Ya}
    method space (line 41) | space(e){const t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)...
    method code (line 41) | code(e){const t=this.rules.block.code.exec(e);if(t){const e=t[0].repla...
    method fences (line 41) | fences(e){const t=this.rules.block.fences.exec(e);if(t){const e=t[0],n...
    method heading (line 41) | heading(e){const t=this.rules.block.heading.exec(e);if(t){let e=t[2].t...
    method hr (line 41) | hr(e){const t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:t[...
    method blockquote (line 41) | blockquote(e){const t=this.rules.block.blockquote.exec(e);if(t){const ...
    method list (line 41) | list(e){let t=this.rules.block.list.exec(e);if(t){let n,r,i,o,s,a,l,c,...
    method html (line 41) | html(e){const t=this.rules.block.html.exec(e);if(t){const e={type:"htm...
    method def (line 41) | def(e){const t=this.rules.block.def.exec(e);if(t){const e=t[1].toLower...
    method table (line 41) | table(e){const t=this.rules.block.table.exec(e);if(t){const e={type:"t...
    method lheading (line 41) | lheading(e){const t=this.rules.block.lheading.exec(e);if(t)return{type...
    method paragraph (line 41) | paragraph(e){const t=this.rules.block.paragraph.exec(e);if(t){const e=...
    method text (line 41) | text(e){const t=this.rules.block.text.exec(e);if(t)return{type:"text",...
    method escape (line 41) | escape(e){const t=this.rules.inline.escape.exec(e);if(t)return{type:"e...
    method tag (line 41) | tag(e){const t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.st...
    method link (line 41) | link(e){const t=this.rules.inline.link.exec(e);if(t){const e=t[2].trim...
    method reflink (line 41) | reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.r...
    method emStrong (line 41) | emStrong(e,t,n=""){let r=this.rules.inline.emStrong.lDelim.exec(e);if(...
    method codespan (line 41) | codespan(e){const t=this.rules.inline.code.exec(e);if(t){let e=t[2].re...
    method br (line 41) | br(e){const t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t...
    method del (line 41) | del(e){const t=this.rules.inline.del.exec(e);if(t)return{type:"del",ra...
    method autolink (line 41) | autolink(e,t){const n=this.rules.inline.autolink.exec(e);if(n){let e,r...
    method url (line 41) | url(e,t){let n;if(n=this.rules.inline.url.exec(e)){let e,r;if("@"===n[...
    method inlineText (line 41) | inlineText(e,t){const n=this.rules.inline.text.exec(e);if(n){let e;ret...
  function bl (line 2) | function bl(e,t,n){Za=e,vl(e,t,n)}
  function vl (line 2) | function vl(e,t,n){for(var r=!!(1&e.mode);null!==Za;){var i=Za,o=i.child...
  function xl (line 2) | function xl(e){for(;null!==Za;){var t=Za;if(8772&t.flags){var n=t.altern...
  function wl (line 2) | function wl(e){for(;null!==Za;){var t=Za;if(t===e){Za=null;break}var n=t...
  function kl (line 2) | function kl(e){for(;null!==Za;){var t=Za;try{switch(t.tag){case 0:case 1...
    method constructor (line 41) | constructor(e){this.tokens=[],this.tokens.links=Object.create(null),th...
    method rules (line 41) | static get rules(){return{block:bl,inline:vl}}
    method lex (line 41) | static lex(e,t){return new kl(t).lex(e)}
    method lexInline (line 41) | static lexInline(e,t){return new kl(t).inlineTokens(e)}
    method lex (line 41) | lex(e){let t;for(e=e.replace(/\r\n|\r/g,"\n"),this.blockTokens(e,this....
    method blockTokens (line 41) | blockTokens(e,t=[]){let n,r,i,o;for(e=this.options.pedantic?e.replace(...
    method inline (line 41) | inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}
    method inlineTokens (line 41) | inlineTokens(e,t=[]){let n,r,i,o,s,a,l=e;if(this.tokens.links){const e...
  function ec (line 2) | function ec(){return 6&Cl?Ke():-1!==Zl?Zl:Zl=Ke()}
  function tc (line 2) | function tc(e){return 1&e.mode?2&Cl&&0!==Tl?Tl&-Tl:null!==go.transition?...
  function nc (line 2) | function nc(e,t,n,r){if(50<Xl)throw Xl=0,Kl=null,Error(o(185));yt(e,n,r)...
  function rc (line 2) | function rc(e,t){var n=e.callbackNode;!function(e,t){for(var n=e.suspend...
  function ic (line 2) | function ic(e,t){if(Zl=-1,Jl=0,6&Cl)throw Error(o(327));var n=e.callback...
  function oc (line 2) | function oc(e,t){var n=Fl;return e.current.memoizedState.isDehydrated&&(...
  function sc (line 2) | function sc(e){null===zl?zl=e:zl.push.apply(zl,e)}
  function ac (line 2) | function ac(e,t){for(t&=~Ml,t&=~Dl,e.suspendedLanes|=t,e.pingedLanes&=~t...
  function lc (line 2) | function lc(e){if(6&Cl)throw Error(o(327));kc();var t=dt(e,0);if(!(1&t))...
  function cc (line 2) | function cc(e,t){var n=Cl;Cl|=1;try{return e(t)}finally{0===(Cl=n)&&(Ul=...
    method constructor (line 41) | constructor(e,t,n,r,i){this.expanded=!1,this.operations=[],on(this),th...
    method toggle (line 41) | toggle(){this.expanded=!this.expanded}
  function uc (line 2) | function uc(e){null!==Gl&&0===Gl.tag&&!(6&Cl)&&kc();var t=Cl;Cl|=1;var n...
  function pc (line 2) | function pc(){Il=Rl.current,Oi(Rl)}
  function dc (line 2) | function dc(e,t){e.finishedWork=null,e.finishedLanes=0;var n=e.timeoutHa...
  function fc (line 2) | function fc(e,t){for(;;){var n=Pl;try{if(Ao(),is.current=Zs,us){for(var ...
  function hc (line 2) | function hc(){var e=Ol.current;return Ol.current=Zs,null===e?Zs:e}
  function mc (line 2) | function mc(){0!==Nl&&3!==Nl&&2!==Nl||(Nl=4),null===jl||!(268435455&Ll)&...
  function gc (line 2) | function gc(e,t){var n=Cl;Cl|=2;var r=hc();for(jl===e&&Tl===t||(ql=null,...
  function yc (line 2) | function yc(){for(;null!==Pl;)vc(Pl)}
  function bc (line 2) | function bc(){for(;null!==Pl&&!Qe();)vc(Pl)}
  function vc (line 2) | function vc(e){var t=Sl(e.alternate,e,Il);e.memoizedProps=e.pendingProps...
  function xc (line 2) | function xc(e){var t=e;do{var n=t.alternate;if(e=t.return,32768&t.flags)...
  function wc (line 2) | function wc(e,t,n){var r=vt,i=Al.transition;try{Al.transition=null,vt=1,...
  function kc (line 2) | function kc(){if(null!==Gl){var e=xt(Ql),t=Al.transition,n=vt;try{if(Al....
    method constructor (line 41) | constructor(e,t,n=new Pi({})){this.options=n,this.allowMergeRefs=!1,th...
    method validate (line 41) | validate(e){if(void 0===e.openapi)throw new Error("Document must be va...
    method isRef (line 41) | isRef(e){return!!e&&void 0!==e.$ref&&null!==e.$ref}
    method deref (line 41) | deref(e,t=[],n=!1){const r=null==e?void 0:e["x-refsStack"];if(t=wc(t,r...
    method mergeRefs (line 41) | mergeRefs(e,t,n){const r=e,{$ref:i}=r,o=vc(r,["$ref"]),s=Object.keys(o...
    method mergeAllOf (line 41) | mergeAllOf(e,t,n){var r;if(e["x-circular-ref"])return e;if(void 0===(e...
    method findDerived (line 41) | findDerived(e){const t={},n=this.spec.components&&this.spec.components...
    method hoistOneOfs (line 41) | hoistOneOfs(e,t){if(void 0===e.allOf)return e;const n=e.allOf;for(let ...
  function Sc (line 2) | function Sc(e,t,n){e=zo(e,t=fa(0,t=ca(n,t),1),1),t=ec(),null!==e&&(yt(e,...
  function Ec (line 2) | function Ec(e,t,n){if(3===e.tag)Sc(e,e,n);else for(;null!==t;){if(3===t....
  function Oc (line 2) | function Oc(e,t,n){var r=e.pingCache;null!==r&&r.delete(t),t=ec(),e.ping...
  function _c (line 2) | function _c(e,t){0===t&&(1&e.mode?(t=ut,!(130023424&(ut<<=1))&&(ut=41943...
  function Ac (line 2) | function Ac(e){var t=e.memoizedState,n=0;null!==t&&(n=t.retryLane),_c(e,n)}
  function Cc (line 2) | function Cc(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,i=e.mem...
  function jc (line 2) | function jc(e,t){return Ye(e,t)}
  function Pc (line 2) | function Pc(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this....
  function Tc (line 2) | function Tc(e,t,n,r){return new Pc(e,t,n,r)}
  function Ic (line 2) | function Ic(e){return!(!(e=e.prototype)||!e.isReactComponent)}
  function Rc (line 2) | function Rc(e,t){var n=e.alternate;return null===n?((n=Tc(e.tag,t,e.key,...
  function Nc (line 2) | function Nc(e,t,n,r,i,s){var a=2;if(r=e,"function"==typeof e)Ic(e)&&(a=1...
  function $c (line 2) | function $c(e,t,n,r){return(e=Tc(7,e,r,t)).lanes=n,e}
  function Lc (line 2) | function Lc(e,t,n,r){return(e=Tc(22,e,r,t)).elementType=R,e.lanes=n,e.st...
  function Dc (line 2) | function Dc(e,t,n){return(e=Tc(6,e,null,t)).lanes=n,e}
  function Mc (line 2) | function Mc(e,t,n){return(t=Tc(4,null!==e.children?e.children:[],e.key,t...
  function Fc (line 2) | function Fc(e,t,n,r,i){this.tag=t,this.containerInfo=e,this.finishedWork...
    method constructor (line 41) | constructor(e,t,n,r){this.mime=n;const{resolved:i}=e.deref(t);this.val...
    method getExternalValue (line 41) | getExternalValue(e){return this.externalValueUrl?(this.externalValueUr...
  function zc (line 2) | function zc(e,t,n,r,i,o,s,a,l){return e=new Fc(e,t,n,a,l),1===t?(t=1,!0=...
  function Bc (line 2) | function Bc(e){if(!e)return Ai;e:{if(Ue(e=e._reactInternals)!==e||1!==e....
  function Uc (line 2) | function Uc(e,t,n,r,i,o,s,a,l){return(e=zc(n,r,!0,e,0,o,0,a,l)).context=...
  function qc (line 2) | function qc(e,t,n,r){var i=t.current,o=ec(),s=tc(i);return n=Bc(n),null=...
  function Vc (line 2) | function Vc(e){return(e=e.current).child?(e.child.tag,e.child.stateNode)...
    method constructor (line 41) | constructor(e,t,n,r,i){var o,s,a,l,c;this.expanded=void 0,on(this);con...
    method toggle (line 41) | toggle(){this.expanded=!this.expanded}
    method collapse (line 41) | collapse(){this.expanded=!1}
    method expand (line 41) | expand(){this.expanded=!0}
  function Wc (line 2) | function Wc(e,t){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var...
  function Hc (line 2) | function Hc(e,t){Wc(e,t),(e=e.alternate)&&Wc(e,t)}
  function Gc (line 2) | function Gc(e){this._internalRoot=e}
  function Qc (line 2) | function Qc(e){this._internalRoot=e}
  function Xc (line 2) | function Xc(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeTy...
  function Kc (line 2) | function Kc(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeTy...
  function Zc (line 2) | function Zc(){}
  function Jc (line 2) | function Jc(e,t,n,r,i){var o=n._reactRootContainer;if(o){var s=o;if("fun...
  function n (line 2) | function n(e,t){var n=e.length;e.push(t);e:for(;0<n;){var r=n-1>>>1,i=e[...
  function r (line 2) | function r(e){return 0===e.length?null:e[0]}
  function i (line 2) | function i(e){if(0===e.length)return null;var t=e[0],n=e.pop();if(n!==t)...
  function o (line 2) | function o(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function x (line 2) | function x(e){for(var t=r(u);null!==t;){if(null===t.callback)i(u);else{i...
  function w (line 2) | function w(e){if(g=!1,x(e),!m)if(null!==r(c))m=!0,R(k);else{var t=r(u);n...
    method constructor (line 2) | constructor(e){super(e),this.name="S2OError"}
  function k (line 2) | function k(e,n){m=!1,g&&(g=!1,b(_),_=-1),h=!0;var o=f;try{for(x(n),d=r(c...
  function j (line 2) | function j(){return!(t.unstable_now()-C<A)}
  function P (line 2) | function P(){if(null!==O){var e=t.unstable_now();C=e;var n=!0;try{n=O(!0...
  function R (line 2) | function R(e){O=e,E||(E=!0,S())}
  function N (line 2) | function N(e,n){_=y((function(){e(t.unstable_now())}),n)}
  function y (line 2) | function y(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n...
  function b (line 2) | function b(){}
  function v (line 2) | function v(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n...
    method constructor (line 2) | constructor(e,t){g(e),t||(t={}),this.options=t,this.set=[],this.patter...
    method debug (line 2) | debug(){}
    method make (line 2) | make(){const e=this.pattern,t=this.options;if(!t.nocomment&&"#"===e.ch...
    method parseNegate (line 2) | parseNegate(){if(this.options.nonegate)return;const e=this.pattern;let...
    method matchOne (line 2) | matchOne(e,t,n){var r=this.options;this.debug("matchOne",{this:this,fi...
    method braceExpand (line 2) | braceExpand(){return m(this.pattern,this.options)}
    method parse (line 2) | parse(e,t){g(e);const n=this.options;if("**"===e){if(!n.noglobstar)ret...
    method makeRe (line 2) | makeRe(){if(this.regexp||!1===this.regexp)return this.regexp;const e=t...
    method match (line 2) | match(e,t=this.partial){if(this.debug("match",e,this.pattern),this.com...
    method defaults (line 2) | static defaults(e){return r.defaults(e).Minimatch}
  function O (line 2) | function O(e,t,r){var i,o={},s=null,a=null;if(null!=t)for(i in void 0!==...
  function _ (line 2) | function _(e){return"object"==typeof e&&null!==e&&e.$$typeof===n}
  function C (line 2) | function C(e,t){return"object"==typeof e&&null!==e&&null!=e.key?function...
  function j (line 2) | function j(e,t,i,o,s){var a=typeof e;"undefined"!==a&&"boolean"!==a||(e=...
  function P (line 2) | function P(e,t,n){if(null==e)return e;var r=[],i=0;return j(e,r,"","",(f...
  function T (line 2) | function T(e){if(-1===e._status){var t=e._result;(t=t()).then((function(...
  function $ (line 2) | function $(){throw Error("act(...) is not supported in production builds...
  function t (line 2) | function t(e){return e.replace(/\~1/g,"/").replace(/~0/g,"~")}
  function n (line 2) | function n(n,r){if("string"!=typeof n)throw new Error("slugify: string a...
  function f (line 2) | function f(){P=$=T=I=R=N=a}
  function h (line 2) | function h(e){return parseFloat(e)||0}
  function m (line 2) | function m(){n={top:t.pageYOffset,left:t.pageXOffset}}
  function g (line 2) | function g(){if(t.pageXOffset!=n.left)return m(),void T();t.pageYOffset!...
  function y (line 2) | function y(e){setTimeout((function(){t.pageYOffset!=n.top&&(n.top=t.page...
  function b (line 2) | function b(){for(var e=i.length-1;e>=0;e--)v(i[e])}
  function v (line 2) | function v(e){if(e.inited){var t=n.top<=e.limit.start?0:n.top>=e.limit.e...
    method constructor (line 2) | constructor(e,t){g(e),t||(t={}),this.options=t,this.set=[],this.patter...
    method debug (line 2) | debug(){}
    method make (line 2) | make(){const e=this.pattern,t=this.options;if(!t.nocomment&&"#"===e.ch...
    method parseNegate (line 2) | parseNegate(){if(this.options.nonegate)return;const e=this.pattern;let...
    method matchOne (line 2) | matchOne(e,t,n){var r=this.options;this.debug("matchOne",{this:this,fi...
    method braceExpand (line 2) | braceExpand(){return m(this.pattern,this.options)}
    method parse (line 2) | parse(e,t){g(e);const n=this.options;if("**"===e){if(!n.noglobstar)ret...
    method makeRe (line 2) | makeRe(){if(this.regexp||!1===this.regexp)return this.regexp;const e=t...
    method match (line 2) | match(e,t=this.partial){if(this.debug("match",e,this.pattern),this.com...
    method defaults (line 2) | static defaults(e){return r.defaults(e).Minimatch}
  function x (line 2) | function x(e){isNaN(parseFloat(e.computed.top))||e.isCell||(e.inited=!0,...
  function w (line 2) | function w(e){var t=!0;e.clone&&function(e){e.clone.parentNode.removeChi...
    method constructor (line 2) | constructor(e){super(e),this.name="S2OError"}
  function k (line 2) | function k(){for(var e=i.length-1;e>=0;e--)x(i[e])}
  function S (line 2) | function S(){for(var e=i.length-1;e>=0;e--)w(i[e])}
  function E (line 2) | function E(e){var t=getComputedStyle(e),n=e.parentNode,r=getComputedStyl...
  function O (line 2) | function O(e){for(var t=0;e;)t+=e.offsetTop,e=e.offsetParent;return t}
  function _ (line 2) | function _(e){var n=e.getBoundingClientRect();return{doc:{top:n.top+t.pa...
  function A (line 2) | function A(){r=setInterval((function(){!function(){for(var e=i.length-1;...
  function C (line 2) | function C(){clearInterval(r)}
  function j (line 2) | function j(){o&&(document[l]?C():A())}
  function P (line 2) | function P(){o||(m(),k(),t.addEventListener("scroll",g),t.addEventListen...
  function T (line 2) | function T(){if(o){S();for(var e=i.length-1;e>=0;e--)i[e]=E(i[e].node);k...
  function I (line 2) | function I(){t.removeEventListener("scroll",g),t.removeEventListener("wh...
  function R (line 2) | function R(){I(),S()}
  function N (line 2) | function N(){for(R();i.length;)i.pop()}
  function $ (line 2) | function $(e){for(var t=i.length-1;t>=0;t--)if(i[t].node===e)return;var ...
  function n (line 2) | function n(e){for(var n=-1,r=0;r<t.length;r++)if(t[r].identifier===e){n=...
  function r (line 2) | function r(e,r){for(var o={},s=[],a=0;a<e.length;a++){var l=e[a],c=r.bas...
  function i (line 2) | function i(e,t){var n=t.domAPI(t);return n.update(e),function(t){if(t){i...
  class w (line 2) | class w extends Error{constructor(e){super(e),this.name="S2OError"}}
    method constructor (line 2) | constructor(e){super(e),this.name="S2OError"}
  function k (line 2) | function k(e,t){let n=new w(e);if(n.options=t,!t.promise)throw n;t.promi...
  function S (line 2) | function S(e,t,n){n.warnOnly?t[n.warnProperty||"x-s2o-warning"]=e:k(e,n)}
  function E (line 2) | function E(e,t){m.walkSchema(e,{},{},(function(e,n,r){!function(e){if(e[...
  function O (line 2) | function O(e,t,n){let r=n.payload.options;if(u(e,t)){if(e[t].startsWith(...
  function _ (line 2) | function _(e){for(let t in e)for(let n in e[t]){let r=g.sanitise(n);n!==...
  function A (line 2) | function A(e,t){if("basic"===e.type&&(e.type="http",e.scheme="basic"),"o...
  function C (line 2) | function C(e){return e&&!e["x-s2o-delete"]}
  function j (line 2) | function j(e,t){if(e.$ref)e.$ref=e.$ref.replace("#/responses/","#/compon...
  function P (line 2) | function P(e,t){if(e.$ref.indexOf("#/parameters/")>=0){let t=e.$ref.spli...
  function T (line 2) | function T(e,t,n,r,i,o,s){let a,l={},u=!0;if(t&&t.consumes&&"string"==ty...
  function I (line 2) | function I(e,t){for(let n in e)n.startsWith("x-")&&!n.startsWith("x-s2o"...
  function R (line 2) | function R(e,t,n,r,i){if(!e)return!1;if(e.$ref&&"string"==typeof e.$ref)...
  function N (line 2) | function N(e,t,n,r,o){for(let s in e){let a=e[s];a&&a["x-trace"]&&"objec...
  function $ (line 2) | function $(e){return e&&e.url&&"string"==typeof e.url?(e.url=e.url.split...
  function L (line 2) | function L(e,t,n){if(void 0===e.info||null===e.info){if(!t.patch)return ...
  function D (line 2) | function D(e,t,n){if(void 0===e.paths){if(!t.patch)return n(new w("(Patc...
  function M (line 2) | function M(e,t,n){return o(n,new Promise((function(n,r){if(e||(e={}),t.o...
  function F (line 2) | function F(e,t,n){return o(n,new Promise((function(n,r){let i=null,o=nul...
  function e (line 2) | function e(){}
  function c (line 2) | function c(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!i(e,n)}...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function r (line 2) | function r(e){var i=n[e];if(void 0!==i)return i.exports;var o=n[e]={id:e...
  function s (line 2) | function s(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;...
  function l (line 2) | function l(){return"undefined"!=typeof globalThis?globalThis:"undefined"...
  function y (line 2) | function y(){m||s("Proxy not available")}
  function b (line 2) | function b(e){var t=!1;return function(){if(!t)return t=!0,e.apply(this,...
  function x (line 2) | function x(e){return"function"==typeof e}
  function w (line 2) | function w(e){switch(typeof e){case"string":case"symbol":case"number":re...
    method constructor (line 2) | constructor(e){super(e),this.name="S2OError"}
  function k (line 2) | function k(e){return null!==e&&"object"==typeof e}
  function S (line 2) | function S(e){if(!k(e))return!1;var t=Object.getPrototypeOf(e);if(null==...
  function E (line 2) | function E(e){var t=null==e?void 0:e.constructor;return!!t&&("GeneratorF...
  function O (line 2) | function O(e,t,n){p(e,t,{enumerable:!1,writable:!0,configurable:!0,value...
  function _ (line 2) | function _(e,t,n){p(e,t,{enumerable:!1,writable:!1,configurable:!0,value...
  function A (line 2) | function A(e,t){var n="isMobX"+e;return t.prototype[n]=!0,function(e){re...
  function C (line 2) | function C(e){return e instanceof Map}
  function j (line 2) | function j(e){return e instanceof Set}
  function I (line 2) | function I(e){return null===e?null:"object"==typeof e?""+e:e}
  function R (line 2) | function R(e,t){return d.hasOwnProperty.call(e,t)}
  function $ (line 2) | function $(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.en...
  function L (line 2) | function L(e,t,n){return t&&$(e.prototype,t),n&&$(e,n),Object.defineProp...
  function D (line 2) | function D(){return D=Object.assign?Object.assign.bind():function(e){for...
  function M (line 2) | function M(e,t){e.prototype=Object.create(t.prototype),e.prototype.const...
  function F (line 2) | function F(e,t){return F=Object.setPrototypeOf?Object.setPrototypeOf.bin...
  function z (line 2) | function z(e){if(void 0===e)throw new ReferenceError("this hasn't been i...
  function B (line 2) | function B(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Ar...
  function U (line 2) | function U(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e[...
  function q (line 2) | function q(e){var t=function(e){if("object"!=typeof e||null===e)return e...
  function W (line 2) | function W(e){return Object.assign((function(t,n){H(t,n,e)}),e)}
  function H (line 2) | function H(e,t,n){R(e,V)||O(e,V,D({},e[V])),function(e){return e.annotat...
  function e (line 2) | function e(e){void 0===e&&(e="Atom"),this.name_=void 0,this.isPendingUno...
  function X (line 2) | function X(e,t,n){void 0===t&&(t=v),void 0===n&&(n=v);var r=new G(e);ret...
  function Z (line 2) | function Z(e,t,n){return Gt(e)?e:Array.isArray(e)?Te.array(e,{name:n}):S...
  function J (line 2) | function J(e){return e}
  function te (line 2) | function te(e,t){return{annotationType_:e,options_:t,make_:ne,extend_:re}}
  function ne (line 2) | function ne(e,t,n,r){var i;if(null!=(i=this.options_)&&i.bound)return nu...
  function re (line 2) | function re(e,t,n,r){var i=ie(e,this,t,n);return e.defineProperty_(t,i,r)}
  function ie (line 2) | function ie(e,t,n,r,i){var o,s,a,l,c,u,p,d;void 0===i&&(i=ut.safeDescrip...
  function oe (line 2) | function oe(e,t){return{annotationType_:e,options_:t,make_:se,extend_:ae}}
  function se (line 2) | function se(e,t,n,r){var i;if(r===e.target_)return null===this.extend_(e...
  function ae (line 2) | function ae(e,t,n,r){var i,o=le(e,this,0,n,null==(i=this.options_)?void ...
  function le (line 2) | function le(e,t,n,r,i,o){var s;void 0===o&&(o=ut.safeDescriptors),s=r,t....
  function ce (line 2) | function ce(e,t){return{annotationType_:e,options_:t,make_:ue,extend_:pe}}
  function ue (line 2) | function ue(e,t,n){return null===this.extend_(e,t,n,!1)?0:1}
  function pe (line 2) | function pe(e,t,n,r){return i=n,this.annotationType_,i.get,e.defineCompu...
  function de (line 2) | function de(e,t){return{annotationType_:e,options_:t,make_:fe,extend_:he}}
  function fe (line 2) | function fe(e,t,n){return null===this.extend_(e,t,n,!1)?0:1}
  function he (line 2) | function he(e,t,n,r){var i,o;return this.annotationType_,e.defineObserva...
  function ye (line 2) | function ye(e){return{annotationType_:me,options_:e,make_:be,extend_:ve}}
  function be (line 2) | function be(e,t,n,r){var i,o,s,a;if(n.get)return $e.make_(e,t,n,r);if(n....
  function ve (line 2) | function ve(e,t,n,r){var i,o,s;return n.get?$e.extend_(e,t,n,r):n.set?e....
  function we (line 2) | function we(e){return e||xe}
  function Ae (line 2) | function Ae(e){return!0===e.deep?Z:!1===e.deep?J:(t=e.defaultDecorator)&...
  function Ce (line 2) | function Ce(e,t,n){if(!w(t))return Gt(e)?e:S(e)?Te.object(e,t,n):Array.i...
  function Be (line 2) | function Be(e,t,n,r){function i(){return function(e,t,n,r,i){var o=funct...
  function Ue (line 2) | function Ue(e){var t=ut.allowStateChanges;return ut.allowStateChanges=e,t}
  function qe (line 2) | function qe(e){ut.allowStateChanges=e}
  function t (line 2) | function t(t,n,r,i,o){var s;return void 0===r&&(r="ObservableValue"),voi...
  function e (line 2) | function e(e){this.dependenciesState_=He.NOT_TRACKING_,this.observing_=[...
  function p (line 2) | function p(){e(a)}
    method constructor (line 2) | constructor(e,n){this.rawConfig=e,this.configFile=n,this.ignore={},thi...
    method resolveIgnore (line 2) | resolveIgnore(e){if(e&&(0,s.doesYamlFileExist)(e)){this.ignore=(0,o.pa...
    method saveIgnore (line 2) | saveIgnore(){const e=this.configFile?i.dirname(this.configFile):proces...
    method addIgnore (line 2) | addIgnore(e){const t=this.ignore,n=e.location[0];if(void 0===n.pointer...
    method addProblemToIgnore (line 2) | addProblemToIgnore(e){const t=e.location[0];if(void 0===t.pointer)retu...
    method extendTypes (line 2) | extendTypes(e,t){let n=e;for(const e of this.plugins)if(void 0!==e.typ...
    method getRuleSettings (line 2) | getRuleSettings(e,t){this._usedRules.add(e),this._usedVersions.add(t);...
    method getPreprocessorSettings (line 2) | getPreprocessorSettings(e,t){this._usedRules.add(e),this._usedVersions...
    method getDecoratorSettings (line 2) | getDecoratorSettings(e,t){this._usedRules.add(e),this._usedVersions.ad...
    method getUnusedRules (line 2) | getUnusedRules(){const e=[],t=[],n=[];for(const r of Array.from(this._...
    method getRulesForOasVersion (line 2) | getRulesForOasVersion(e){switch(e){case a.SpecMajorVersion.OAS3:const ...
    method skipRules (line 2) | skipRules(e){for(const t of e||[])for(const e of Object.values(a.SpecV...
    method skipPreprocessors (line 2) | skipPreprocessors(e){for(const t of e||[])for(const e of Object.values...
    method skipDecorators (line 2) | skipDecorators(e){for(const t of e||[])for(const e of Object.values(a....
  function Ke (line 2) | function Ke(e){return e instanceof Xe}
  function Ze (line 2) | function Ze(e){switch(e.dependenciesState_){case He.UP_TO_DATE_:return!1...
  function Je (line 2) | function Je(e,t,n){var r=it(!0);st(e),e.newObserving_=new Array(e.observ...
  function et (line 2) | function et(e){var t=e.observing_;e.observing_=[];for(var n=t.length;n--...
  function tt (line 2) | function tt(e){var t=nt();try{return e()}finally{rt(t)}}
  function nt (line 2) | function nt(){var e=ut.trackingDerivation;return ut.trackingDerivation=n...
  function rt (line 2) | function rt(e){ut.trackingDerivation=e}
  function it (line 2) | function it(e){var t=ut.allowStateReads;return ut.allowStateReads=e,t}
  function ot (line 2) | function ot(e){ut.allowStateReads=e}
  function st (line 2) | function st(e){if(e.dependenciesState_!==He.UP_TO_DATE_){e.dependenciesS...
  function pt (line 2) | function pt(e,t){e.observers_.delete(t),0===e.observers_.size&&dt(e)}
  function dt (line 2) | function dt(e){!1===e.isPendingUnobservation_&&(e.isPendingUnobservation...
  function ft (line 2) | function ft(){0===ut.inBatch&&(ut.batchId=ut.batchId<Number.MAX_SAFE_INT...
  function ht (line 2) | function ht(){if(0==--ut.inBatch){xt();for(var e=ut.pendingUnobservation...
  function mt (line 2) | function mt(e){var t=ut.trackingDerivation;return null!==t?(t.runId_!==e...
  function gt (line 2) | function gt(e){e.lowestObserverState_!==He.STALE_&&(e.lowestObserverStat...
  function e (line 2) | function e(e,t,n,r){void 0===e&&(e="Reaction"),this.name_=void 0,this.on...
  function xt (line 2) | function xt(){ut.inBatch>0||ut.isRunningReactions||vt(wt)}
  function wt (line 2) | function wt(){ut.isRunningReactions=!0;for(var e=ut.pendingReactions,t=0...
  function jt (line 2) | function jt(e){return function(t,n){return x(t)?Be(t.name||"<unnamed act...
  function It (line 2) | function It(e){return x(e)&&!0===e.isMobxAction}
  function Lt (line 2) | function Lt(e,t,n){return Dt($t,e,t,n)}
  function Dt (line 2) | function Dt(e,t,n,r){var i="function"==typeof r?Qn(t,n):Qn(t),o=x(r)?r:n...
  function Ft (line 2) | function Ft(e){!0===e.isolateGlobalState&&function(){if((ut.pendingReact...
  function zt (line 2) | function zt(e){var t,n={name:e.name_};return e.observing_&&e.observing_....
  function Ut (line 2) | function Ut(){this.message="FLOW_CANCELLED"}
  function l (line 2) | function l(e){var t;s=void 0;try{t=Pt(r+" - runid: "+i+" - yield "+a++,o...
  function c (line 2) | function c(e){var t;s=void 0;try{t=Pt(r+" - runid: "+i+" - yield "+a++,o...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function u (line 2) | function u(e){if(!x(null==e?void 0:e.then))return e.done?t(e.value):(s=P...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  function Ht (line 2) | function Ht(e){x(e.cancel)&&e.cancel()}
  function Yt (line 2) | function Yt(e){return!0===(null==e?void 0:e.isMobXFlow)}
  function Gt (line 2) | function Gt(e){return function(e,t){return!!e&&(void 0!==t?!!Ln(e)&&e[Y]...
  function Qt (line 2) | function Qt(e,t){void 0===t&&(t=void 0),ft();try{return e.apply(t)}final...
  function Xt (line 2) | function Xt(e){return e[Y]}
  function Zt (line 2) | function Zt(e){return void 0!==e.interceptors_&&e.interceptors_.length>0}
  function Jt (line 2) | function Jt(e,t){var n=e.interceptors_||(e.interceptors_=[]);return n.pu...
  function en (line 2) | function en(e,t){var n=nt();try{for(var r=[].concat(e.interceptors_||[])...
  function tn (line 2) | function tn(e){return void 0!==e.changeListeners_&&e.changeListeners_.le...
  function nn (line 2) | function nn(e,t){var n=e.changeListeners_||(e.changeListeners_=[]);retur...
  function rn (line 2) | function rn(e,t){var n=nt(),r=e.changeListeners_;if(r){for(var i=0,o=(r=...
  function on (line 2) | function on(e,t,n){return Zn((function(){var r=Rn(e,n)[Y];null!=t||(t=fu...
  function e (line 2) | function e(e,t,n,r){void 0===e&&(e="ObservableArray"),this.owned_=void 0...
  function un (line 2) | function un(e,t,n,r){return void 0===n&&(n="ObservableArray"),void 0===r...
  function dn (line 2) | function dn(e,t){"function"==typeof Array.prototype[e]&&(pn[e]=t(e))}
  function fn (line 2) | function fn(e){return function(){var t=this[Y];t.atom_.reportObserved();...
  function hn (line 2) | function hn(e){return function(t,n){var r=this,i=this[Y];return i.atom_....
  function mn (line 2) | function mn(e){return function(){var t=this,n=this[Y];n.atom_.reportObse...
  function vn (line 2) | function vn(e){return k(e)&&bn(e[Y])}
  function e (line 2) | function e(e,t,n){var r=this;void 0===t&&(t=Z),void 0===n&&(n="Observabl...
  function e (line 2) | function e(e,t,n){var r=this;void 0===t&&(t=Z),void 0===n&&(n="Observabl...
  function e (line 2) | function e(e,t,n,r){void 0===t&&(t=new Map),void 0===r&&(r=ge),this.targ...
  function Rn (line 2) | function Rn(e,t){var n;if(R(e,Y))return e;var r=null!=(n=null==t?void 0:...
  function $n (line 2) | function $n(e){return Pn[e]||(Pn[e]={get:function(){return this[Y].getOb...
  function Ln (line 2) | function Ln(e){return!!k(e)&&Nn(e[Y])}
  function Dn (line 2) | function Dn(e,t,n){var r;null==(r=e.target_[V])||delete r[n]}
  function r (line 2) | function r(t,n,r,i){var o;return void 0===r&&(r="ObservableArray"),void ...
  function Wn (line 2) | function Wn(e){return{enumerable:!1,configurable:!0,get:function(){retur...
  function Hn (line 2) | function Hn(e){p(Vn.prototype,""+e,Wn(e))}
  function Yn (line 2) | function Yn(e){if(e>Un){for(var t=Un;t<e+100;t++)Hn(t);Un=e}}
  function Gn (line 2) | function Gn(e,t,n){return new Vn(e,t,n)}
  function Qn (line 2) | function Qn(e,t){if("object"==typeof e&&null!==e){if(vn(e))return void 0...
  function Xn (line 2) | function Xn(e,t){return e||s(29),void 0!==t?Xn(Qn(e,t)):Q(e)||Qe(e)||kt(...
  function Kn (line 2) | function Kn(e,t){var n;if(void 0!==t)n=Qn(e,t);else{if(It(e))return e.na...
  function Zn (line 2) | function Zn(e){var t=nt(),n=Ue(!0);ft();try{return e()}finally{ht(),qe(n...
  function er (line 2) | function er(e,t,n){return void 0===n&&(n=-1),tr(e,t,n)}
  function tr (line 2) | function tr(e,t,n,r,i){if(e===t)return 0!==e||1/e==1/t;if(null==e||null=...
  function nr (line 2) | function nr(e){return vn(e)?e.slice():C(e)||_n(e)||j(e)||jn(e)?Array.fro...
  function rr (line 2) | function rr(e){return e[Symbol.iterator]=ir,e}
  function ir (line 2) | function ir(){return this}
  function or (line 2) | function or(){return or=Object.assign?Object.assign.bind():function(e){f...
  function sr (line 2) | function sr(e,t){return sr=Object.setPrototypeOf?Object.setPrototypeOf.b...
  function ar (line 2) | function ar(e){return ar=Object.setPrototypeOf?Object.getPrototypeOf.bin...
  function lr (line 2) | function lr(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construc...
  function cr (line 2) | function cr(e){var t="function"==typeof Map?new Map:void 0;return cr=fun...
  function r (line 2) | function r(t){return function(e){if(void 0===e)throw new ReferenceError(...
  function pr (line 2) | function pr(e){return Math.round(255*e)}
  function dr (line 2) | function dr(e,t,n){return pr(e)+","+pr(t)+","+pr(n)}
  function fr (line 2) | function fr(e,t,n,r){if(void 0===r&&(r=dr),0===t)return r(n,n,n);var i=(...
  function Sr (line 2) | function Sr(e){if("string"!=typeof e)throw new ur(3);var t=function(e){i...
  function Er (line 2) | function Er(e){return function(e){var t,n=e.red/255,r=e.green/255,i=e.bl...
  function _r (line 2) | function _r(e){var t=e.toString(16);return 1===t.length?"0"+t:t}
  function Ar (line 2) | function Ar(e){return _r(Math.round(255*e))}
  function Cr (line 2) | function Cr(e,t,n){return Or("#"+Ar(e)+Ar(t)+Ar(n))}
  function jr (line 2) | function jr(e,t,n){return fr(e,t,n,Cr)}
  function Pr (line 2) | function Pr(e,t,n){if("number"==typeof e&&"number"==typeof t&&"number"==...
  function Tr (line 2) | function Tr(e,t,n,r){if("string"==typeof e&&"number"==typeof t){var i=Sr...
  function Lr (line 2) | function Lr(e){if("object"!=typeof e)throw new ur(8);if(Rr(e))return Tr(...
  function Dr (line 2) | function Dr(e,t,n){return function(){var r=n.concat(Array.prototype.slic...
  function Mr (line 2) | function Mr(e){return Dr(e,e.length,[])}
  function Fr (line 2) | function Fr(e,t,n){return Math.max(e,Math.min(t,n))}
  function zr (line 2) | function zr(e,t){if("transparent"===t)return t;var n=Er(t);return Lr(or(...
  function Ur (line 2) | function Ur(e,t){if("transparent"===t)return t;var n=Er(t);return Lr(or(...
  function Vr (line 2) | function Vr(e){if("transparent"===e)return 0;var t=Sr(e),n=Object.keys(t...
  function Wr (line 2) | function Wr(e,t){if("transparent"===t)return t;var n=Er(t);return Lr(or(...
  function Qr (line 2) | function Qr(e,t,n,r){void 0===t&&(t=Yr),void 0===n&&(n=Gr),void 0===r&&(...
  function Xr (line 2) | function Xr(e,t){if("transparent"===t)return t;var n=Sr(t);return Tr(or(...
  function ti (line 2) | function ti(e){return"undefined"!=typeof document?document.querySelector...
  function ni (line 2) | function ni(e,t=!0){const n=e.parentNode;if(!n)return;const r=window.get...
  function oi (line 2) | function oi(e,t){const n=[];for(let r=0;r<e.length-1;r++)n.push(t(e[r],!...
  function si (line 2) | function si(e,t){const n={};for(const r in e)e.hasOwnProperty(r)&&(n[r]=...
  function ai (line 2) | function ai(e){return e.endsWith("/")?e.substring(0,e.length-1):e}
  function li (line 2) | function li(e){return!isNaN(parseFloat(e))&&isFinite(e)}
  function di (line 2) | function di(e){return ii()(e)||e.toString().toLowerCase().replace(/\s+/g...
  function fi (line 2) | function fi(e){return"undefined"==typeof URL?new(r(8381).URL)(e):new URL...
  function hi (line 2) | function hi(e){return e.replace(/["\\]/g,"\\$&")}
  function mi (line 2) | function mi(e){return Array.isArray(e)}
  function gi (line 2) | function gi(e){return"boolean"==typeof e}
  function bi (line 2) | function bi(e,t){const n=yi[e];return void 0!==t?n[t]:n}
  function Ci (line 2) | function Ci(e,t){return void 0===e?t||!1:"string"==typeof e?"false"!==e:e}
  function ji (line 2) | function ji(e){return"string"==typeof e?parseInt(e,10):"number"==typeof ...
  class Pi (line 2) | class Pi{static normalizeExpandResponses(e){if("all"===e)return"all";if(...
    method normalizeExpandResponses (line 2) | static normalizeExpandResponses(e){if("all"===e)return"all";if("string...
    method normalizeHideHostname (line 2) | static normalizeHideHostname(e){return!!e}
    method normalizeScrollYOffset (line 2) | static normalizeScrollYOffset(e){if("string"==typeof e&&!li(e)){const ...
    method normalizeShowExtensions (line 2) | static normalizeShowExtensions(e){if(void 0===e)return!1;if(""===e)ret...
    method normalizeSideNavStyle (line 2) | static normalizeSideNavStyle(e){const t=vi.SummaryOnly;if("string"!=ty...
    method normalizePayloadSampleIdx (line 2) | static normalizePayloadSampleIdx(e){return"number"==typeof e?Math.max(...
    method normalizeJsonSampleExpandLevel (line 2) | static normalizeJsonSampleExpandLevel(e){return"all"===e?1/0:isNaN(Num...
    method normalizeGeneratedPayloadSamplesMaxDepth (line 2) | static normalizeGeneratedPayloadSamplesMaxDepth(e){return isNaN(Number...
    method constructor (line 2) | constructor(e,t={}){var n,r,i,o,s;const a=(e=Ai(Ai({},t),e)).theme&&e....
  function t (line 2) | function t(e,r,l,c,d){for(var f,h,m,g,x,k=0,S=0,E=0,O=0,_=0,I=0,N=m=f=0,...
  function n (line 2) | function n(e,t,n){var i=t.trim().split(m);t=i;var o=i.length,s=e.length;...
  function r (line 2) | function r(e,t,n){var r=t.charCodeAt(0);switch(33>r&&(r=(t=t.trim()).cha...
  function i (line 2) | function i(e,t,n,r){var s=e+";",a=2*t+3*n+4*r;if(944===a){e=s.indexOf(":...
  function o (line 2) | function o(e,t){var n=e.indexOf(1===t?":":"{"),r=e.substring(0,3!==t?n:1...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 2) | function s(e,t){var n=i(t,t.charCodeAt(0),t.charCodeAt(1),t.charCodeAt(2...
  function a (line 2) | function a(e,t,n,r,i,o,s,a,l,u){for(var p,d=0,f=t;d<R;++d)switch(p=I[d]....
  function l (line 2) | function l(e){return void 0!==(e=e.prefix)&&(N=null,e?"function"!=typeof...
  function c (line 2) | function c(e,n){var r=e;if(33>r.charCodeAt(0)&&(r=r.trim()),r=[r],0<R){v...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function Li (line 2) | function Li(e){var t=Object.create(null);return function(n){return void ...
  function Bi (line 2) | function Bi(){return(Bi=Object.assign||function(e){for(var t=1;t<argumen...
  function Hi (line 2) | function Hi(e){return"function"==typeof e}
  function Yi (line 2) | function Yi(e){return e.displayName||e.name||"Component"}
  function Gi (line 2) | function Gi(e){return e&&"string"==typeof e.styledComponentId}
  function Ji (line 2) | function Ji(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t...
  function e (line 2) | function e(e){this.groupSizes=new Uint32Array(512),this.length=512,this....
  function e (line 2) | function e(e){var t=this.element=fo(e);t.appendChild(document.createText...
  function e (line 2) | function e(e){var t=this.element=fo(e);this.nodes=t.childNodes,this.leng...
  function e (line 2) | function e(e){this.rules=[],this.length=0}
  function e (line 2) | function e(e,t,n){void 0===e&&(e=Wi),void 0===t&&(t={}),this.options=Bi(...
  function ko (line 2) | function ko(e){var t,n="";for(t=Math.abs(e);t>52;t=t/52|0)n=wo(t%52)+n;r...
  function Oo (line 2) | function Oo(e){for(var t=0;t<e.length;t+=1){var n=e[t];if(Hi(n)&&!Gi(n))...
  function e (line 2) | function e(e,t,n){this.rules=e,this.staticRulesId="",this.isStatic=(void...
  function Po (line 2) | function Po(e){var t,n,r,i,o=void 0===e?Wi:e,s=o.options,a=void 0===s?Wi...
  function $o (line 2) | function $o(){return(0,n.useContext)(To)||Ro}
  function Lo (line 2) | function Lo(){return(0,n.useContext)(Io)||No}
  function Do (line 2) | function Do(e){var t=(0,n.useState)(e.stylisPlugins),r=t[0],i=t[1],o=$o(...
  function e (line 2) | function e(e,t){var n=this;this.inject=function(e,t){void 0===t&&(t=No);...
  function qo (line 2) | function qo(e){return Fo.test(e)?e.replace(zo,Uo).replace(Bo,"-ms-"):e}
  function Wo (line 2) | function Wo(e,t,n,r){if(Array.isArray(e)){for(var i,o=[],s=0,a=e.length;...
  function Yo (line 2) | function Yo(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t...
  function Ko (line 2) | function Ko(e){return e.replace(Qo,"-").replace(Xo,"")}
  function Jo (line 2) | function Jo(e){return"string"==typeof e&&!0}
  function ns (line 2) | function ns(e,t,n){var r=e[n];es(t)&&es(r)?rs(r,t):e[n]=t}
  function rs (line 2) | function rs(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t...
  function os (line 2) | function os(e){var t=(0,n.useContext)(is),r=(0,n.useMemo)((function(){re...
  function as (line 2) | function as(e,t,r){var i=Gi(e),o=!Jo(e),s=t.attrs,a=void 0===s?Vi:s,l=t....
  function e (line 2) | function e(e,t){this.rules=e,this.componentId=t,this.isStatic=Oo(e),vo.r...
  function ps (line 2) | function ps(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),i=1;i<t...
  function ds (line 2) | function ds(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t...
  method lessThan (line 2) | lessThan(e,t,n){return(...r)=>ms`
  method greaterThan (line 6) | greaterThan(e){return(...t)=>ms`
  method between (line 10) | between(e,t){return(...n)=>ms`
  function ws (line 14) | function ws(e){return t=>{if(t.theme.extensionsHook)return t.theme.exten...
  class Ss (line 17) | class Ss extends n.Component{constructor(e){super(e),this.state={error:v...
    method constructor (line 17) | constructor(e){super(e),this.state={error:void 0}}
    method componentDidCatch (line 17) | componentDidCatch(e){return this.setState({error:e}),!1}
    method render (line 17) | render(){return this.state.error?n.createElement(ks,null,n.createEleme...
  class As (line 41) | class As extends n.PureComponent{render(){return n.createElement("div",{...
    method render (line 41) | render(){return n.createElement("div",{style:{textAlign:"center"}},n.c...
  class Bs (line 41) | class Bs{static baseName(e,t=1){const n=Bs.parse(e);return n[n.length-t]...
    method baseName (line 41) | static baseName(e,t=1){const n=Bs.parse(e);return n[n.length-t]}
    method dirName (line 41) | static dirName(e,t=1){const n=Bs.parse(e);return Ms.compile(n.slice(0,...
    method relative (line 41) | static relative(e,t){const n=Bs.parse(e);return Bs.parse(t).slice(n.le...
    method parse (line 41) | static parse(e){let t=e;return"#"===t.charAt(0)&&(t=t.substring(1)),zs...
    method join (line 41) | static join(e,t){const n=Bs.parse(e).concat(t);return Ms.compile(n)}
    method get (line 41) | static get(e,t){return Ms.get(e,t)}
    method compile (line 41) | static compile(e){return Ms.compile(e)}
    method escape (line 41) | static escape(e){return Ms.escape(e)}
  function Js (line 41) | function Js(e){return"string"==typeof e&&/\dxx/i.test(e)}
  function ea (line 41) | function ea(e,t=!1){if("default"===e)return t?"error":"success";let n="s...
  function na (line 41) | function na(e){return e in ta}
  function ia (line 41) | function ia(e,t=e.type){if(e["x-circular-ref"])return!0;if(void 0!==e.on...
  function oa (line 41) | function oa(e){return-1!==e.search(/json/i)}
  function sa (line 41) | function sa(e,t,n){return mi(e)?e.map((e=>e.toString())).join(n):"object...
  function aa (line 41) | function aa(e,t){return mi(e)?(console.warn("deepObject style cannot be ...
  function la (line 41) | function la(e,t,n){const r="__redoc_param_name__",i=t?"*":"";return qs.p...
  function ca (line 41) | function ca(e,t){return oa(t)?JSON.stringify(e):(console.warn(`Parameter...
  function ua (line 41) | function ua(e,t){return e.in?decodeURIComponent(function(e,t){const{name...
  function da (line 41) | function da(e){return pa.test(e||"")}
  function fa (line 41) | function fa(e){var t;const[n]=(null==(t=null==e?void 0:e.match(pa))?void...
  function ha (line 41) | function ha(e,t,n){let r;return void 0!==t&&void 0!==n?r=t===n?`= ${t} $...
  function ma (line 41) | function ma(e){const t=[],n=ha("characters",e.minLength,e.maxLength);voi...
  function ga (line 41) | function ga(e,t=[]){const n=[],r=[],i=[];return e.forEach((e=>{e.require...
  function ya (line 41) | function ya(e,t){return[...e].sort(((e,n)=>e[t].localeCompare(n[t])))}
  function ba (line 41) | function ba(e,t){const n=void 0===e?function(e){try{const t=fi(e);return...
  function Ea (line 41) | function Ea(e,t){return Object.keys(e).filter((e=>!0===t?e.startsWith("x...
  function Aa (line 41) | function Aa(e,t=_a){t=t.toLowerCase();let n=Oa.languages[t];return n||(n...
  function Ma (line 41) | function Ma(e,t,n){if("function"==typeof n.value)return function(e,t,n){...
  function Fa (line 41) | function Fa(e){let t=1;return"-"===e[0]&&(t=-1,e=e.substr(1)),(n,r)=>-1=...
  class qa (line 41) | class qa{constructor(){this.emit=()=>{this._emiter.emit(Ua,this.currentI...
    method constructor (line 41) | constructor(){this.emit=()=>{this._emiter.emit(Ua,this.currentId)},thi...
    method currentId (line 41) | get currentId(){return ei?decodeURIComponent(window.location.hash.subs...
    method linkForId (line 41) | linkForId(e){return e?"#"+e:""}
    method subscribe (line 41) | subscribe(e){const t=this._emiter.addListener(Ua,e);return()=>t.remove...
    method bind (line 41) | bind(){ei&&window.addEventListener("hashchange",this.emit,!1)}
    method dispose (line 41) | dispose(){ei&&window.removeEventListener("hashchange",this.emit)}
    method replace (line 41) | replace(e,t=!1){ei&&null!=e&&e!==this.currentId&&(t?window.history.rep...
  class Ha (line 41) | class Ha{constructor(){this.map=new Map,this.prevTerm=""}add(e){this.map...
    method constructor (line 41) | constructor(){this.map=new Map,this.prevTerm=""}
    method add (line 41) | add(e){this.map.set(e,new Wa(e))}
    method delete (line 41) | delete(e){this.map.delete(e)}
    method addOnly (line 41) | addOnly(e){this.map.forEach(((t,n)=>{-1===e.indexOf(n)&&(t.unmark(),th...
    method clearAll (line 41) | clearAll(){this.unmark(),this.map.clear()}
    method mark (line 41) | mark(e){(e||this.prevTerm)&&(this.map.forEach((t=>{t.unmark(),t.mark(e...
    method unmark (line 41) | unmark(){this.map.forEach((e=>e.unmark())),this.prevTerm=""}
  function el (line 41) | function el(e,t){if(t){if(Ga.test(e))return e.replace(Qa,Ja)}else if(Xa....
  function nl (line 41) | function nl(e){return e.replace(tl,((e,t)=>"colon"===(t=t.toLowerCase())...
  function il (line 41) | function il(e,t){e="string"==typeof e?e:e.source,t=t||"";const n={replac...
  function al (line 41) | function al(e,t,n){if(e){let e;try{e=decodeURIComponent(nl(n)).replace(o...
  function fl (line 41) | function fl(e,t){const n=e.replace(/\|/g,((e,t,n)=>{let r=!1,i=t;for(;--...
  function hl (line 41) | function hl(e,t,n){const r=e.length;if(0===r)return"";let i=0;for(;i<r;)...
  function ml (line 41) | function ml(e,t){if(t<1)return"";let n="";for(;t>1;)1&t&&(n+=e),t>>=1,e+...
  function gl (line 41) | function gl(e,t,n,r){const i=t.href,o=t.title?el(t.title):null,s=e[1].re...
  class yl (line 41) | class yl{constructor(e){this.options=e||Ya}space(e){const t=this.rules.b...
    method constructor (line 41) | constructor(e){this.options=e||Ya}
    method space (line 41) | space(e){const t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)...
    method code (line 41) | code(e){const t=this.rules.block.code.exec(e);if(t){const e=t[0].repla...
    method fences (line 41) | fences(e){const t=this.rules.block.fences.exec(e);if(t){const e=t[0],n...
    method heading (line 41) | heading(e){const t=this.rules.block.heading.exec(e);if(t){let e=t[2].t...
    method hr (line 41) | hr(e){const t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:t[...
    method blockquote (line 41) | blockquote(e){const t=this.rules.block.blockquote.exec(e);if(t){const ...
    method list (line 41) | list(e){let t=this.rules.block.list.exec(e);if(t){let n,r,i,o,s,a,l,c,...
    method html (line 41) | html(e){const t=this.rules.block.html.exec(e);if(t){const e={type:"htm...
    method def (line 41) | def(e){const t=this.rules.block.def.exec(e);if(t){const e=t[1].toLower...
    method table (line 41) | table(e){const t=this.rules.block.table.exec(e);if(t){const e={type:"t...
    method lheading (line 41) | lheading(e){const t=this.rules.block.lheading.exec(e);if(t)return{type...
    method paragraph (line 41) | paragraph(e){const t=this.rules.block.paragraph.exec(e);if(t){const e=...
    method text (line 41) | text(e){const t=this.rules.block.text.exec(e);if(t)return{type:"text",...
    method escape (line 41) | escape(e){const t=this.rules.inline.escape.exec(e);if(t)return{type:"e...
    method tag (line 41) | tag(e){const t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.st...
    method link (line 41) | link(e){const t=this.rules.inline.link.exec(e);if(t){const e=t[2].trim...
    method reflink (line 41) | reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.r...
    method emStrong (line 41) | emStrong(e,t,n=""){let r=this.rules.inline.emStrong.lDelim.exec(e);if(...
    method codespan (line 41) | codespan(e){const t=this.rules.inline.code.exec(e);if(t){let e=t[2].re...
    method br (line 41) | br(e){const t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t...
    method del (line 41) | del(e){const t=this.rules.inline.del.exec(e);if(t)return{type:"del",ra...
    method autolink (line 41) | autolink(e,t){const n=this.rules.inline.autolink.exec(e);if(n){let e,r...
    method url (line 41) | url(e,t){let n;if(n=this.rules.inline.url.exec(e)){let e,r;if("@"===n[...
    method inlineText (line 41) | inlineText(e,t){const n=this.rules.inline.text.exec(e);if(n){let e;ret...
  function xl (line 41) | function xl(e){return e.replace(/---/g,"—").replace(/--/g,"–").replace(/...
  function wl (line 41) | function wl(e){let t,n,r="";const i=e.length;for(t=0;t<i;t++)n=e.charCod...
  class kl (line 41) | class kl{constructor(e){this.tokens=[],this.tokens.links=Object.create(n...
    method constructor (line 41) | constructor(e){this.tokens=[],this.tokens.links=Object.create(null),th...
    method rules (line 41) | static get rules(){return{block:bl,inline:vl}}
    method lex (line 41) | static lex(e,t){return new kl(t).lex(e)}
    method lexInline (line 41) | static lexInline(e,t){return new kl(t).inlineTokens(e)}
    method lex (line 41) | lex(e){let t;for(e=e.replace(/\r\n|\r/g,"\n"),this.blockTokens(e,this....
    method blockTokens (line 41) | blockTokens(e,t=[]){let n,r,i,o;for(e=this.options.pedantic?e.replace(...
    method inline (line 41) | inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}
    method inlineTokens (line 41) | inlineTokens(e,t=[]){let n,r,i,o,s,a,l=e;if(this.tokens.links){const e...
  class Sl (line 41) | class Sl{constructor(e){this.options=e||Ya}code(e,t,n){const r=(t||"").m...
    method constructor (line 41) | constructor(e){this.options=e||Ya}
    method code (line 41) | code(e,t,n){const r=(t||"").match(/\S*/)[0];if(this.options.highlight)...
    method blockquote (line 41) | blockquote(e){return`<blockquote>\n${e}</blockquote>\n`}
    method html (line 41) | html(e){return e}
    method heading (line 41) | heading(e,t,n,r){return this.options.headerIds?`<h${t} id="${this.opti...
    method hr (line 41) | hr(){return this.options.xhtml?"<hr/>\n":"<hr>\n"}
    method list (line 41) | list(e,t,n){const r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"'...
    method listitem (line 41) | listitem(e){return`<li>${e}</li>\n`}
    method checkbox (line 41) | checkbox(e){return"<input "+(e?'checked="" ':"")+'disabled="" type="ch...
    method paragraph (line 41) | paragraph(e){return`<p>${e}</p>\n`}
    method table (line 41) | table(e,t){return t&&(t=`<tbody>${t}</tbody>`),"<table>\n<thead>\n"+e+...
    method tablerow (line 41) | tablerow(e){return`<tr>\n${e}</tr>\n`}
    method tablecell (line 41) | tablecell(e,t){const n=t.header?"th":"td";return(t.align?`<${n} align=...
    method strong (line 41) | strong(e){return`<strong>${e}</strong>`}
    method em (line 41) | em(e){return`<em>${e}</em>`}
    method codespan (line 41) | codespan(e){return`<code>${e}</code>`}
    method br (line 41) | br(){return this.options.xhtml?"<br/>":"<br>"}
    method del (line 41) | del(e){return`<del>${e}</del>`}
    method link (line 41) | link(e,t,n){if(null===(e=al(this.options.sanitize,this.options.baseUrl...
    method image (line 41) | image(e,t,n){if(null===(e=al(this.options.sanitize,this.options.baseUr...
    method text (line 41) | text(e){return e}
  class El (line 41) | class El{strong(e){return e}em(e){return e}codespan(e){return e}del(e){r...
    method strong (line 41) | strong(e){return e}
    method em (line 41) | em(e){return e}
    method codespan (line 41) | codespan(e){return e}
    method del (line 41) | del(e){return e}
    method html (line 41) | html(e){return e}
    method text (line 41) | text(e){return e}
    method link (line 41) | link(e,t,n){return""+n}
    method image (line 41) | image(e,t,n){return""+n}
    method br (line 41) | br(){return""}
  class Ol (line 41) | class Ol{constructor(){this.seen={}}serialize(e){return e.toLowerCase()....
    method constructor (line 41) | constructor(){this.seen={}}
    method serialize (line 41) | serialize(e){return e.toLowerCase().trim().replace(/<[!\/a-z].*?>/gi,"...
    method getNextSafeSlug (line 41) | getNextSafeSlug(e,t){let n=e,r=0;if(this.seen.hasOwnProperty(n)){r=thi...
    method slug (line 41) | slug(e,t={}){const n=this.serialize(e);return this.getNextSafeSlug(n,t...
  class _l (line 41) | class _l{constructor(e){this.options=e||Ya,this.options.renderer=this.op...
    method constructor (line 41) | constructor(e){this.options=e||Ya,this.options.renderer=this.options.r...
    method parse (line 41) | static parse(e,t){return new _l(t).parse(e)}
    method parseInline (line 41) | static parseInline(e,t){return new _l(t).parseInline(e)}
    method parse (line 41) | parse(e,t=!0){let n,r,i,o,s,a,l,c,u,p,d,f,h,m,g,y,b,v,x,w="";const k=e...
    method parseInline (line 41) | parseInline(e,t){t=t||this.renderer;let n,r,i,o="";const s=e.length;fo...
  class Al (line 41) | class Al{constructor(e){this.options=e||Ya}static passThroughHooks=new S...
    method constructor (line 41) | constructor(e){this.options=e||Ya}
    method preprocess (line 41) | preprocess(e){return e}
    method postprocess (line 41) | postprocess(e){return e}
  function Cl (line 41) | function Cl(e,t){return(n,r,i)=>{"function"==typeof r&&(i=r,r=null);cons...
  function jl (line 41) | function jl(e,t,n){return Cl(kl.lex,_l.parse)(e,t,n)}
  class Bl (line 41) | class Bl{constructor(e,t){this.options=e,this.parentId=t,this.headings=[...
    method constructor (line 41) | constructor(e,t){this.options=e,this.parentId=t,this.headings=[],this....
    method containsComponent (line 41) | static containsComponent(e,t){return new RegExp(zl.replace(/{component...
    method getTextBeforeHading (line 41) | static getTextBeforeHading(e,t){const n=e.search(new RegExp(`^##?\\s+$...
    method saveHeading (line 41) | saveHeading(e,t,n=this.headings,r){e=e.replace(/&#(\d+);/g,((e,t)=>Str...
    method flattenHeadings (line 41) | flattenHeadings(e){if(void 0===e)return[];const t=[];for(const n of e)...
    method attachHeadingsDescriptions (line 41) | attachHeadingsDescriptions(e){const t=e=>new RegExp(`##?\\s+${e.name.r...
    method renderMd (line 41) | renderMd(e,t=!1){const n=t?{renderer:this.headingEnhanceRenderer}:void...
    method extractHeadings (line 41) | extractHeadings(e){this.renderMd(e,!0),this.attachHeadingsDescriptions...
    method renderMdWithComponents (line 41) | renderMdWithComponents(e){const t=this.options&&this.options.allowedMd...
  function Ul (line 41) | function Ul(e){if(!e)return{};const t=/([\w-]+)\s*=\s*(?:{([^}]+?)}|"([^...
  class ql (line 41) | class ql{constructor(e,t=new Pi({})){this.parser=e,this.options=t,Object...
    method constructor (line 41) | constructor(e,t=new Pi({})){this.parser=e,this.options=t,Object.assign...
    method getDownloadUrls (line 41) | getDownloadUrls(){return(this.options.downloadUrls?this.options.downlo...
    method getDownloadLink (line 41) | getDownloadLink(e){if(e)return e;if(this.parser.specUrl)return this.pa...
    method getDownloadFileName (line 41) | getDownloadFileName(){return this.parser.specUrl||this.options.downloa...
  class Kl (line 41) | class Kl{constructor(e,t){const n=t.spec.components&&t.spec.components.s...
    method constructor (line 41) | constructor(e,t){const n=t.spec.components&&t.spec.components.security...
  class cc (line 41) | class cc{constructor(e,t,n,r,i){this.expanded=!1,this.operations=[],on(t...
    method constructor (line 41) | constructor(e,t,n,r,i){this.expanded=!1,this.operations=[],on(this),th...
    method toggle (line 41) | toggle(){this.expanded=!this.expanded}
  function xc (line 41) | function xc(e,t){return t&&e[e.length-1]!==t?[...e,t]:e}
  function wc (line 41) | function wc(e,t){return t?e.concat(t):e}
  class kc (line 41) | class kc{constructor(e,t,n=new Pi({})){this.options=n,this.allowMergeRef...
    method constructor (line 41) | constructor(e,t,n=new Pi({})){this.options=n,this.allowMergeRefs=!1,th...
    method validate (line 41) | validate(e){if(void 0===e.openapi)throw new Error("Document must be va...
    method isRef (line 41) | isRef(e){return!!e&&void 0!==e.$ref&&null!==e.$ref}
    method deref (line 41) | deref(e,t=[],n=!1){const r=null==e?void 0:e["x-refsStack"];if(t=wc(t,r...
    method mergeRefs (line 41) | mergeRefs(e,t,n){const r=e,{$ref:i}=r,o=vc(r,["$ref"]),s=Object.keys(o...
    method mergeAllOf (line 41) | mergeAllOf(e,t,n){var r;if(e["x-circular-ref"])return e;if(void 0===(e...
    method findDerived (line 41) | findDerived(e){const t={},n=this.spec.components&&this.spec.components...
    method hoistOneOfs (line 41) | hoistOneOfs(e,t){if(void 0===e.allOf)return e;const n=e.allOf;for(let ...
  method constructor (line 41) | constructor(e,t,n,r,i=!1,o=[]){this.options=r,this.refsStack=o,this.type...
  method activateOneOf (line 41) | activateOneOf(e){this.activeOneOf=e}
  method hasType (line 41) | hasType(e){return this.type===e||mi(this.type)&&this.type.includes(e)}
  method init (line 41) | init(t,n){var r,i,o,s,a,l,c,u;const p=this.schema;if(this.isCircular=!!p...
  method initOneOf (line 41) | initOneOf(t,n){if(this.oneOf=t.map(((t,r)=>{const{resolved:i,refsStack:o...
  method initDiscriminator (line 41) | initDiscriminator(t,n){const r=Dc(t);this.discriminatorProp=r.propertyNa...
  method initConditionalOperators (line 41) | initConditionalOperators(t,n){const r=t,{if:i,else:o={},then:s={}}=r,a=(...
  function Lc (line 41) | function Lc(e,t,n,r,i){const o=t.properties||t.prefixItems||t.items||{},...
  function Dc (line 41) | function Dc(e){return e.discriminator||e["x-discriminator"]}
  class Fc (line 41) | class Fc{constructor(e,t,n,r){this.mime=n;const{resolved:i}=e.deref(t);t...
    method constructor (line 41) | constructor(e,t,n,r){this.mime=n;const{resolved:i}=e.deref(t);this.val...
    method getExternalValue (line 41) | getExternalValue(e){return this.externalValueUrl?(this.externalValueUr...
  class Vc (line 41) | class Vc{constructor(e,t,n,r,i){var o,s,a,l,c;this.expanded=void 0,on(th...
    method constructor (line 41) | constructor(e,t,n,r,i){var o,s,a,l,c;this.expanded=void 0,on(this);con...
    method toggle (line 41) | toggle(){this.expanded=!this.expanded}
    method collapse (line 41) | collapse(){this.expanded=!1}
    method expand (line 41) | expand(){this.expanded=!0}
  function Hc (line 41) | function Hc(e){return e<10?"0"+e:e}
  function Yc (line 41) | function Yc(e,t){return t>e.length?e.repeat(Math.trunc(t/e.length)+1).su...
  function Gc (line 41) | function Gc(...e){const t=e=>e&&"object"==typeof e;return e.reduce(((e,n...
  function Qc (line 41) | function Qc(e){return{value:"object"===e?{}:"array"===e?[]:void 0}}
  function Xc (line 41) | function Xc(e,t){t&&e.pop()}
  function Kc (line 41) | function Kc(e,t={},n={}){const{value:r}=e,{propertyName:i}=n,{name:o,pre...
  function Jc (line 41) | function Jc(e){if(void 0!==e.type)return Array.isArray(e.type)?0===e.typ...
  function nu (line 41) | function nu(e){let t;return void 0!==e.const?t=e.const:void 0!==e.exampl...
  function ru (line 41) | function ru(e){const t=nu(e);if(void 0!==t)return{value:t,readOnly:e.rea...
  function iu (line 41) | function iu(e,t,n,r){if(r){if(tu.includes(e))return Qc(Jc(e));tu.push(e)...
  function ou (line 41) | function ou(e){let t=0;if("number"!==e.type||"float"!==e.format&&"double...
  function su (line 41) | function su(e,t){return e}
  function au (line 41) | function au(e,t,n){let r=1;if(e)switch(e){case"?":r=0;break;case"*":r=su...
  function lu (line 41) | function lu({min:e,max:t,omitTime:n,omitDate:r}){let i=function(e,t,n){v...
  function cu (line 41) | function cu(e,t,n,r,i=!1){if(r&&i)return function(e){let t,n,r,i=!1;e in...
  function hu (line 41) | function hu(e,t,n){let r=Object.assign({},fu,t);eu={},tu=[];let i=iu(e,r...
  function mu (line 41) | function mu(e,t){du[e]=t}
  class gu (line 41) | class gu{constructor(e,t,n,r,i){this.name=t,this.isRequestType=n,this.sc...
    method constructor (line 41) | constructor(e,t,n,r,i){this.name=t,this.isRequestType=n,this.schema=r....
    method generateExample (line 41) | generateExample(e,t){const n={skipReadOnly:this.isRequestType,skipWrit...
  class xu (line 41) | class xu{constructor(e,t,n,r){this.isRequestType=n,this.activeMimeIdx=0,...
    method constructor (line 41) | constructor(e,t,n,r){this.isRequestType=n,this.activeMimeIdx=0,on(this...
    method activate (line 41) | activate(e){this.activeMimeIdx=e}
    method active (line 41) | get active(){return this.mediaTypes[this.activeMimeIdx]}
    method hasSample (line 41) | get hasSample(){return this.mediaTypes.filter((e=>!!e.examples)).lengt...
  class wu (line 41) | class wu{constructor({parser:e,infoOrRef:t,options:n,isEvent:r}){const i...
    method constructor (line 41) | constructor({parser:e,infoOrRef:t,options:n,isEvent:r}){const i=!r,{re...
  class Tu (line 41) | class Tu{constructor({parser:e,code:t,defaultAsError:n,infoOrRef:r,optio...
    method constructor (line 41) | constructor({parser:e,code:t,defaultAsError:n,infoOrRef:r,options:i,is...
    method toggle (line 41) | toggle(){this.expanded=!this.expanded}
  function $u (line 41) | function $u(e){return"payload"===e.lang&&e.requestBodyContent}
  class Du (line 41) | class Du{constructor(e,t,n,r,i=!1){var o,s;this.parser=e,this.operationS...
    method constructor (line 41) | constructor(e,t,n,r,i=!1){var o,s;this.parser=e,this.operationSpec=t,t...
    method activate (line 41) | activate(){this.active=!0}
    method deactivate (line 41) | deactivate(){this.active=!1}
    method toggle (line 41) | toggle(){this.expanded=!this.expanded}
    method expand (line 41) | expand(){this.parent&&this.parent.expand()}
    method collapse (line 41) | collapse(){}
    method requestBody (line 41) | get requestBody(){return this.operationSpec.requestBody&&new wu({parse...
    method codeSamples (line 41) | get codeSamples(){const{payloadSampleIdx:e,hideRequestPayloadSample:t}...
    method parameters (line 41) | get parameters(){const e=function(e,t=[],n=[]){const r={};return n.for...
    method responses (line 41) | get responses(){let e=!1;return Object.keys(this.operationSpec.respons...
    method callbacks (line 41) | get callbacks(){return Object.keys(this.operationSpec.callbacks||[]).m...
  function Ju (line 119) | function Ju(e){const{spec:t,specUrl:i,options:o,onLoaded:s,children:a}=e...
  function np (line 146) | function np(e){return n.createElement(tp,{to:e.to})}
  function xp (line 401) | function xp(e){return t=>!!t.type&&t.type.tabsRole===e}
  function Ep (line 401) | function Ep(e,t){return n.Children.map(e,(e=>null===e?null:function(e){r...
  function Op (line 401) | function Op(e,t){return n.Children.forEach(e,(e=>{null!==e&&(wp(e)||Sp(e...
  function _p (line 401) | function _p(e){var t,n,r="";if("string"==typeof e||"number"==typeof e)r+...
  function Cp (line 401) | function Cp(e){let t=0;return Op(e,(e=>{wp(e)&&t++})),t}
  function jp (line 401) | function jp(e){return e&&"getAttribute"in e}
  function Pp (line 401) | function Pp(e){return jp(e)&&e.getAttribute("data-rttab")}
  function Tp (line 401) | function Tp(e){return jp(e)&&"true"===e.getAttribute("aria-disabled")}
  function o (line 401) | function o(t,n){if(t<0||t>=l())return;const{onSelect:r,selectedIndex:i}=...
    method constructor (line 2) | constructor(e,t){this.source=e,this.pointer=t}
    method child (line 2) | child(e){return new o(this.source,i(this.pointer,(Array.isArray(e)?e:[...
    method key (line 2) | key(){return Object.assign(Object.assign({},this),{reportOnKey:!0})}
    method absolutePointer (line 2) | get absolutePointer(){return this.source.absoluteRef+("#/"===this.poin...
  function s (line 401) | function s(e){const t=l();for(let n=e+1;n<t;n++)if(!Tp(c(n)))return n;fo...
  function a (line 401) | function a(e){let t=e;for(;t--;)if(!Tp(c(t)))return t;for(t=l();t-- >e;)...
  function l (line 401) | function l(){const{children:t}=e;return Cp(t)}
  function c (line 401) | function c(e){return t.current[`tabs-${e}`]}
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function u (line 401) | function u(e){let t=e.target;do{if(p(t)){if(Tp(t))return;return void o([...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  function p (line 401) | function p(e){if(!Pp(e))return!1;let t=e.parentElement;do{if(t===i.curre...
    method constructor (line 2) | constructor(e,n){this.rawConfig=e,this.configFile=n,this.ignore={},thi...
    method resolveIgnore (line 2) | resolveIgnore(e){if(e&&(0,s.doesYamlFileExist)(e)){this.ignore=(0,o.pa...
    method saveIgnore (line 2) | saveIgnore(){const e=this.configFile?i.dirname(this.configFile):proces...
    method addIgnore (line 2) | addIgnore(e){const t=this.ignore,n=e.location[0];if(void 0===n.pointer...
    method addProblemToIgnore (line 2) | addProblemToIgnore(e){const t=e.location[0];if(void 0===t.pointer)retu...
    method extendTypes (line 2) | extendTypes(e,t){let n=e;for(const e of this.plugins)if(void 0!==e.typ...
    method getRuleSettings (line 2) | getRuleSettings(e,t){this._usedRules.add(e),this._usedVersions.add(t);...
    method getPreprocessorSettings (line 2) | getPreprocessorSettings(e,t){this._usedRules.add(e),this._usedVersions...
    method getDecoratorSettings (line 2) | getDecoratorSettings(e,t){this._usedRules.add(e),this._usedVersions.ad...
    method getUnusedRules (line 2) | getUnusedRules(){const e=[],t=[],n=[];for(const r of Array.from(this._...
    method getRulesForOasVersion (line 2) | getRulesForOasVersion(e){switch(e){case a.SpecMajorVersion.OAS3:const ...
    method skipRules (line 2) | skipRules(e){for(const t of e||[])for(const e of Object.values(a.SpecV...
    method skipPreprocessors (line 2) | skipPreprocessors(e){for(const t of e||[])for(const e of Object.values...
    method skipDecorators (line 2) | skipDecorators(e){for(const t of e||[])for(const e of Object.values(a....
  function td (line 653) | function td(e){return getComputedStyle(e)}
  function nd (line 653) | function nd(e,t){for(var n in t){var r=t[n];"number"==typeof r&&(r+="px"...
  function rd (line 653) | function rd(e){var t=document.createElement("div");return t.className=e,t}
  function od (line 653) | function od(e,t){if(!id)throw new Error("No element matching method supp...
  function sd (line 653) | function sd(e){e.remove?e.remove():e.parentNode&&e.parentNode.removeChil...
  function ad (line 653) | function ad(e,t){return Array.prototype.filter.call(e.children,(function...
  function ud (line 653) | function ud(e,t){var n=e.element.classList,r=ld.state.scrolling(t);n.con...
  function pd (line 653) | function pd(e,t){cd[t]=setTimeout((function(){return e.isAlive&&e.elemen...
  function md (line 653) | function md(e){if("function"==typeof window.CustomEvent)return new Custo...
  function gd (line 653) | function gd(e,t,n,r,i){var o;if(void 0===r&&(r=!0),void 0===i&&(i=!1),"t...
  function yd (line 653) | function yd(e){return parseInt(e,10)||0}
  function vd (line 653) | function vd(e){var t=e.element,n=Math.floor(t.scrollTop),r=t.getBounding...
  function xd (line 653) | function xd(e,t){return e.settings.minScrollbarLength&&(t=Math.max(t,e.s...
  function wd (line 653) | function wd(e,t){var n=t[0],r=t[1],i=t[2],o=t[3],s=t[4],a=t[5],l=t[6],c=...
  function n (line 653) | function n(n){var r=function(e){var t=e.deltaX,n=-1*e.deltaY;return void...
  function s (line 653) | function s(n,r){t.scrollTop-=r,t.scrollLeft-=n,vd(e)}
  function a (line 653) | function a(e){return e.targetTouches?e.targetTouches[0]:e}
  function l (line 653) | function l(e){return!(e.pointerType&&"pen"===e.pointerType&&0===e.button...
  function c (line 653) | function c(e){if(l(e)){var t=a(e);n.pageX=t.pageX,n.pageY=t.pageY,r=(new...
    method constructor (line 2) | constructor(e,t,n){this.absoluteRef=e,this.body=t,this.mimeType=n}
    method getAst (line 2) | getAst(e){var t;return void 0===this._ast&&(this._ast=null!==(t=e(this...
    method getLines (line 2) | getLines(){return void 0===this._lines&&(this._lines=this.body.split(/...
  function u (line 653) | function u(o){if(l(o)){var c=a(o),u={pageX:c.pageX,pageY:c.pageY},p=u.pa...
    method constructor (line 2) | constructor(e){super(e.message),this.originalError=e,Object.setPrototy...
  function p (line 653) | function p(){e.settings.swipeEasing&&(clearInterval(o),o=setInterval((fu...
    method constructor (line 2) | constructor(e,n){this.rawConfig=e,this.configFile=n,this.ignore={},thi...
    method resolveIgnore (line 2) | resolveIgnore(e){if(e&&(0,s.doesYamlFileExist)(e)){this.ignore=(0,o.pa...
    method saveIgnore (line 2) | saveIgnore(){const e=this.configFile?i.dirname(this.configFile):proces...
    method addIgnore (line 2) | addIgnore(e){const t=this.ignore,n=e.location[0];if(void 0===n.pointer...
    method addProblemToIgnore (line 2) | addProblemToIgnore(e){const t=e.location[0];if(void 0===t.pointer)retu...
    method extendTypes (line 2) | extendTypes(e,t){let n=e;for(const e of this.plugins)if(void 0!==e.typ...
    method getRuleSettings (line 2) | getRuleSettings(e,t){this._usedRules.add(e),this._usedVersions.add(t);...
    method getPreprocessorSettings (line 2) | getPreprocessorSettings(e,t){this._usedRules.add(e),this._usedVersions...
    method getDecoratorSettings (line 2) | getDecoratorSettings(e,t){this._usedRules.add(e),this._usedVersions.ad...
    method getUnusedRules (line 2) | getUnusedRules(){const e=[],t=[],n=[];for(const r of Array.from(this._...
    method getRulesForOasVersion (line 2) | getRulesForOasVersion(e){switch(e){case a.SpecMajorVersion.OAS3:const ...
    method skipRules (line 2) | skipRules(e){for(const t of e||[])for(const e of Object.values(a.SpecV...
    method skipPreprocessors (line 2) | skipPreprocessors(e){for(const t of e||[])for(const e of Object.values...
    method skipDecorators (line 2) | skipDecorators(e){for(const t of e||[])for(const e of Object.values(a....
  class Nd (line 655) | class Nd extends n.Component{constructor(){super(...arguments),this.hand...
    method constructor (line 655) | constructor(){super(...arguments),this.handleRef=e=>{this._container=e}}
    method componentDidMount (line 655) | componentDidMount(){const e=this._container.parentElement&&this._conta...
    method componentDidUpdate (line 655) | componentDidUpdate(){this.inst.update()}
    method componentWillUnmount (line 655) | componentWillUnmount(){this.inst.destroy()}
    method render (line 655) | render(){const{children:e,className:t,updateFn:r}=this.props;return r&...
  function $d (line 655) | function $d(e){return n.createElement(js.Consumer,null,(t=>t.nativeScrol...
  class Xd (line 752) | class Xd{constructor(e,t,n){this.operations=[];const{resolved:r}=e.deref...
    method constructor (line 752) | constructor(e,t,n){this.operations=[];const{resolved:r}=e.deref(n||{})...
    method initWebhooks (line 752) | initWebhooks(e,t,n){for(const r of Object.keys(t)){const i=t[r],o=Obje...
  class Kd (line 752) | class Kd{constructor(e,t,n){const{resolved:r}=e.deref(n);this.id=t,this....
    method constructor (line 752) | constructor(e,t,n){const{resolved:r}=e.deref(n);this.id=t,this.section...
  class Zd (line 752) | class Zd{constructor(e){const t=e.spec.components&&e.spec.components.sec...
    method constructor (line 752) | constructor(e){const t=e.spec.components&&e.spec.components.securitySc...
  class sf (line 752) | class sf{constructor(e,t,n){var r,i,o;this.options=n,this.parser=new kc(...
    method constructor (line 752) | constructor(e,t,n){var r,i,o;this.options=n,this.parser=new kc(e,t,n),...
  class uf (line 752) | class uf{constructor(e,t,n){this.items=[],this.active=!1,this.expanded=!...
    method constructor (line 752) | constructor(e,t,n){this.items=[],this.active=!1,this.expanded=!1,on(th...
    method activate (line 752) | activate(){this.active=!0}
    method expand (line 752) | expand(){this.parent&&this.parent.expand(),this.expanded=!0}
    method collapse (line 752) | collapse(){"group"!==this.type&&(this.expanded=!1)}
    method deactivate (line 752) | deactivate(){this.active=!1}
  class xf (line 752) | class xf{static buildStructure(e,t){const n=e.spec,{schemaDefinitionsTag...
    method buildStructure (line 752) | static buildStructure(e,t){const n=e.spec,{schemaDefinitionsTagName:r}...
    method addMarkdownItems (line 752) | static addMarkdownItems(e,t,n,r){const i=new Bl(r,null==t?void 0:t.id)...
    method getTagGroupsItems (line 752) | static getTagGroupsItems(e,t,n,r,i){const o=[];for(const s of n){const...
    method getTagsItems (line 752) | static getTagsItems(e,t,n,r,i){let o;o=void 0===r?Object.keys(t):r.tag...
    method getOperationsItems (line 752) | static getOperationsItems(e,t,n,r,i){if(0===n.operations.length)return...
    method getTagsWithOperations (line 752) | static getTagsWithOperations(e,t){const{spec:n}=e,r={},i=n["x-webhooks...
    method getTagRelatedSchema (line 752) | static getTagRelatedSchema({parser:e,tag:t,parent:n,schemaDefinitionsT...
  class Of (line 752) | class Of{constructor(e,t,n){this.scroll=t,this.history=n,this.activeItem...
    method constructor (line 752) | constructor(e,t,n){this.scroll=t,this.history=n,this.activeItemIdx=-1,...
    method updateOnHistory (line 752) | static updateOnHistory(e=Va.currentId,t){e&&t.scrollIntoViewBySelector...
    method subscribe (line 752) | subscribe(){this._unsubscribe=this.scroll.subscribe(this.updateOnScrol...
    method toggleSidebar (line 752) | toggleSidebar(){this.sideBarOpened=!this.sideBarOpened}
    method closeSidebar (line 752) | closeSidebar(){this.sideBarOpened=!1}
    method getElementAt (line 752) | getElementAt(e){const t=this.flatItems[e];return t&&ti(`[${Ef}="${hi(t...
    method getElementAtOrFirstChild (line 752) | getElementAtOrFirstChild(e){let t=this.flatItems[e];return t&&"group"=...
    method activeItem (line 752) | get activeItem(){return this.flatItems[this.activeItemIdx]||void 0}
    method activate (line 752) | activate(e,t=!0,n=!1){if((this.activeItem&&this.activeItem.id)!==(e&&e...
    method deactivate (line 752) | deactivate(e){if(void 0!==e)for(e.deactivate();void 0!==e;)e.collapse(...
    method activateAndScroll (line 752) | activateAndScroll(e,t,n){const r=e&&this.getItemById(e.id)||e;this.act...
    method scrollToActive (line 752) | scrollToActive(){this.scroll.scrollIntoView(this.getElementAt(this.act...
    method dispose (line 752) | dispose(){this._unsubscribe(),this._hashUnsubscribe()}
  class jf (line 752) | class jf{constructor(e){this.options=e,this._prevOffsetY=0,this._scrollP...
    method constructor (line 752) | constructor(e){this.options=e,this._prevOffsetY=0,this._scrollParent=e...
    method bind (line 752) | bind(){this._prevOffsetY=this.scrollY(),this._scrollParent&&this._scro...
    method dispose (line 752) | dispose(){this._scrollParent&&this._scrollParent.removeEventListener("...
    method scrollY (line 752) | scrollY(){return"undefined"!=typeof HTMLElement&&this._scrollParent in...
    method isElementBellow (line 752) | isElementBellow(e){if(null!==e)return e.getBoundingClientRect().top>th...
    method isElementAbove (line 752) | isElementAbove(e){if(null===e)return;const t=e.getBoundingClientRect()...
    method subscribe (line 752) | subscribe(e){const t=this._emiter.addListener(Cf,e);return()=>t.remove...
    method scrollIntoView (line 752) | scrollIntoView(e){null!==e&&(e.scrollIntoView(),this._scrollParent&&th...
    method scrollIntoViewBySelector (line 752) | scrollIntoViewBySelector(e){const t=ti(e);this.scrollIntoView(t)}
    method handleScroll (line 752) | handleScroll(){const e=this.scrollY()-this._prevOffsetY>0;this._prevOf...
  class Pf (line 752) | class Pf{constructor(){this.searchWorker=function(){let e;if(ei)try{e=r(...
    method constructor (line 752) | constructor(){this.searchWorker=function(){let e;if(ei)try{e=r(1988)}c...
    method indexItems (line 752) | indexItems(e){const t=e=>{e.forEach((e=>{"group"!==e.type&&this.add(e....
    method add (line 752) | add(e,t,n){this.searchWorker.add(e,t,n)}
    method dispose (line 752) | dispose(){this.searchWorker.terminate(),this.searchWorker.dispose()}
    method search (line 752) | search(e){return this.searchWorker.search(e)}
    method toJS (line 752) | toJS(){return e=this,t=function*(){return this.searchWorker.toJS()},ne...
    method load (line 752) | load(e){this.searchWorker.load(e)}
    method fromExternalJS (line 752) | fromExternalJS(e,t){e&&t&&this.searchWorker.fromExternalJS(e,t)}
  function Df (line 752) | function Df(e){const{Label:t=zd,Dropdown:r=Fd}=e;return 1===e.options.le...
  function ch (line 752) | function ch(e){return function(t){for(var n=arguments.length,r=new Array...
  function uh (line 752) | function uh(e,t){let n=arguments.length>2&&void 0!==arguments[2]?argumen...
  function ph (line 752) | function ph(e){for(let t=0;t<e.length;t++)oh(e,t)||(e[t]=null);return e}
  function dh (line 752) | function dh(e){const t=Wf(null);for(const[n,r]of Mf(e))oh(e,n)&&(Array.i...
  function fh (line 752) | function fh(e,t){for(;null!==e;){const n=Uf(e,t);if(n){if(n.get)return c...
  method createHTML (line 752) | createHTML(e){return e}
  method createScriptURL (line 752) | createScriptURL(e){return e}
  function Fe (line 752) | function Fe(e,t,r){Gf(e,(e=>{e.call(n,t,r,Ae)}))}
  function Xh (line 894) | function Xh(e){var t=e,{inline:r,compact:i}=t,o=((e,t)=>{var n={};for(va...
  class Kh (line 894) | class Kh extends n.Component{render(){const{source:e,inline:t,compact:r,...
    method render (line 894) | render(){const{source
Condensed preview — 279 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,674K chars).
[
  {
    "path": ".dockerignore",
    "chars": 66,
    "preview": "*.pyc\n.venv*\n.vscode\n.mypy_cache\n.coverage\nhtmlcov\n\ndist\ntest.py\n\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 75,
    "preview": "# polar: django-ninja\ncustom: [\"https://www.buymeacoffee.com/djangoninja\"]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 566,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"[BUG] \"\nlabels: ''\nassignees: ''\n\n---\n\n**Describe"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 365,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "chars": 262,
    "preview": "---\nname: Question\nabout: Having troubles implementing something ?\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\nPlease descr"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 118,
    "preview": "version: 2\n\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: monthly\n"
  },
  {
    "path": ".github/workflows/close-old-issues.yml",
    "chars": 6095,
    "preview": "name: Close Old Issues\n\non:\n  workflow_dispatch:\n    inputs:\n      days_old:\n        description: 'Close issues older th"
  },
  {
    "path": ".github/workflows/docs.yml",
    "chars": 235,
    "preview": "name: Docs\n\non:\n  workflow_dispatch:\n\njobs:\n  docs:\n    runs-on: ubuntu-latest\n    \n    steps:\n      - uses: actions/che"
  },
  {
    "path": ".github/workflows/publish.yml",
    "chars": 617,
    "preview": "name: Publish\n\non:\n  release:\n    types: [published]\n  workflow_dispatch:\n\njobs:\n  publish:\n    runs-on: ubuntu-latest\n "
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 559,
    "preview": "name: Test Coverage\n\non:\n  push:\n    branches:\n      - master\n\njobs:\n  test_coverage:\n    runs-on: ubuntu-latest\n    \n  "
  },
  {
    "path": ".github/workflows/test_full.yml",
    "chars": 2765,
    "preview": "name: Full Test\n\non:\n  push:\n  workflow_dispatch:\n  pull_request:\n    types: [assigned, opened, synchronize, reopened]\n\n"
  },
  {
    "path": ".gitignore",
    "chars": 134,
    "preview": "*.pyc\n.venv*\n.vscode\n.mypy_cache\n.coverage\nhtmlcov\n/coverage.xml\n\ndist\ntest.py\n\ndocs/site\n\n.DS_Store\n.idea\n.python-versi"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 539,
    "preview": "repos:\n  - repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v4.2.0\n    hooks:\n      - id: check-yaml\n      "
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1257,
    "preview": "# Contributing\n\nDjango Ninja uses Flit to build, package and publish the project.\n\nto install it use:\n\n```\npip install f"
  },
  {
    "path": "LICENSE",
    "chars": 1086,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2025 Vitaliy Kucheryaviy\n\nPermission is hereby granted, free of charge, to any pers"
  },
  {
    "path": "Makefile",
    "chars": 768,
    "preview": ".DEFAULT_GOAL := help\n\n.PHONY: help\nhelp:\n\t@fgrep -h \"##\" $(MAKEFILE_LIST) | fgrep -v fgrep | sort | awk 'BEGIN {FS = \":"
  },
  {
    "path": "README.md",
    "chars": 3824,
    "preview": "<a href=\"https://github.com/vitalik/django-ninja/issues/383\"><img width=\"814\" alt=\"SCR-20230123-m1t\" src=\"https://user-i"
  },
  {
    "path": "docs/docs/chat.md",
    "chars": 693,
    "preview": "# Ask AI\n\nPlease feel free to share any questions or describe any problems you're encountering. Simply enter your text i"
  },
  {
    "path": "docs/docs/extra.css",
    "chars": 1283,
    "preview": ".doc-module code {\n  white-space: nowrap;\n}\n\n/* Ask AI Button Styles */\n.ask-ai-button-container {\n  display: flex;\n  al"
  },
  {
    "path": "docs/docs/guides/api-docs.md",
    "chars": 4506,
    "preview": "# API Docs\n\n## OpenAPI docs\n\nOnce you configured your Ninja API and started runserver -  go to <a href=\"http://127.0.0.1"
  },
  {
    "path": "docs/docs/guides/async-support.md",
    "chars": 6708,
    "preview": "## Intro\n\nSince **version 3.1**, Django comes with **async views support**. This allows you run efficient concurrent vie"
  },
  {
    "path": "docs/docs/guides/authentication.md",
    "chars": 6490,
    "preview": "# Authentication\n\n## Intro\n\n**Django Ninja** provides several tools to help you deal with authentication and authorizati"
  },
  {
    "path": "docs/docs/guides/decorators.md",
    "chars": 10505,
    "preview": "# Decorators\n\nDjango Ninja provides flexible decorator support to wrap your API operations with additional functionality"
  },
  {
    "path": "docs/docs/guides/errors.md",
    "chars": 4680,
    "preview": "# Handling errors\n\n**Django Ninja** allows you to install custom exception handlers to deal with how you return response"
  },
  {
    "path": "docs/docs/guides/input/body.md",
    "chars": 4719,
    "preview": "# Request Body\n\nRequest bodies are typically used with “create” and “update” operations (POST, PUT, PATCH).\nFor example,"
  },
  {
    "path": "docs/docs/guides/input/file-params.md",
    "chars": 4255,
    "preview": "# File uploads\n\nHandling files are no different from other parameters.\n\n```python hl_lines=\"1 2 5\"\nfrom ninja import Nin"
  },
  {
    "path": "docs/docs/guides/input/filtering.md",
    "chars": 8800,
    "preview": "# Filtering\n\nIf you want to allow the user to filter your querysets by a number of different attributes, it makes sense\n"
  },
  {
    "path": "docs/docs/guides/input/form-params.md",
    "chars": 1827,
    "preview": "# Form data\n\n**Django Ninja** also allows you to parse and validate `request.POST` data\n(aka `application/x-www-form-url"
  },
  {
    "path": "docs/docs/guides/input/operations.md",
    "chars": 1265,
    "preview": "# HTTP Methods\n\n## Defining operations\n\nAn `operation` can be one of the following [HTTP methods](https://developer.mozi"
  },
  {
    "path": "docs/docs/guides/input/path-params.md",
    "chars": 4145,
    "preview": "# Path parameters\nYou can declare path \"parameters\" with the same syntax used by Python format-strings (which luckily al"
  },
  {
    "path": "docs/docs/guides/input/query-params.md",
    "chars": 3080,
    "preview": "# Query parameters\n\nWhen you declare other function parameters that are not part of the path parameters, they are automa"
  },
  {
    "path": "docs/docs/guides/input/request-parsers.md",
    "chars": 1726,
    "preview": "# Request parsers\n\nIn most cases, the default content type for REST API's is JSON, but in case you need to work with\noth"
  },
  {
    "path": "docs/docs/guides/response/config-pydantic.md",
    "chars": 1951,
    "preview": "# Overriding Pydantic Config\n\nThere are many customizations available for a **Django Ninja `Schema`**, via the schema's\n"
  },
  {
    "path": "docs/docs/guides/response/django-pydantic-create-schema.md",
    "chars": 2876,
    "preview": "# Using create_schema\n\nUnder the hood, [`ModelSchema`](django-pydantic.md#modelschema) uses the `create_schema` function"
  },
  {
    "path": "docs/docs/guides/response/django-pydantic.md",
    "chars": 4866,
    "preview": "# Schemas from Django models\n\n\nSchemas are very useful to define your validation rules and responses, but sometimes you "
  },
  {
    "path": "docs/docs/guides/response/index.md",
    "chars": 12188,
    "preview": "# Response Schema\n\n**Django Ninja** allows you to define the schema of your responses both for validation and documentat"
  },
  {
    "path": "docs/docs/guides/response/pagination.md",
    "chars": 8814,
    "preview": "# Pagination\n\n**Django Ninja** comes with a pagination support. This allows you to split large result sets into individu"
  },
  {
    "path": "docs/docs/guides/response/response-renderers.md",
    "chars": 3245,
    "preview": "# Response renderers\n\nThe most common response type for a REST API is usually JSON.\n**Django Ninja** also has support fo"
  },
  {
    "path": "docs/docs/guides/response/temporal_response.md",
    "chars": 1436,
    "preview": "# Altering the Response\n\nSometimes you'll want to change the response just before it gets served, for example, to add a "
  },
  {
    "path": "docs/docs/guides/routers.md",
    "chars": 5349,
    "preview": "# Routers\n\nReal world applications can almost never fit all logic into a single file. \n\n**Django Ninja** comes with an e"
  },
  {
    "path": "docs/docs/guides/testing.md",
    "chars": 2659,
    "preview": "# Testing\n\n**Django Ninja** is fully compatible with standard [django test client](https://docs.djangoproject.com/en/dev"
  },
  {
    "path": "docs/docs/guides/throttling.md",
    "chars": 4171,
    "preview": "# Throttling\n\nThrottles allows to control the rate of requests that clients can make to an API. Django Ninja allows to s"
  },
  {
    "path": "docs/docs/guides/urls.md",
    "chars": 1761,
    "preview": "# Reverse Resolution of URLS\n\nA reverse URL name is generated for each method in a Django Ninja Schema (or `Router`).\n\n#"
  },
  {
    "path": "docs/docs/guides/versioning.md",
    "chars": 1498,
    "preview": "# Versioning\n\n## Different API version numbers\n\nWith **Django Ninja** it's easy to run multiple API versions from a sing"
  },
  {
    "path": "docs/docs/help.md",
    "chars": 1487,
    "preview": "# Help / Get Help\n\n## Do you like Django Ninja?\n\nIf you like this project, there is a tiny thing you can do to let us kn"
  },
  {
    "path": "docs/docs/index.md",
    "chars": 3690,
    "preview": "# Django Ninja - Fast Django REST Framework\n\n<div style=\"background-color: black; color: red; font-size: 16px; padding: "
  },
  {
    "path": "docs/docs/javascripts/ask-ai-button.js",
    "chars": 1414,
    "preview": "// Add \"Ask AI\" button to the Material for MkDocs navbar\ndocument.addEventListener('DOMContentLoaded', function() {\n    "
  },
  {
    "path": "docs/docs/motivation.md",
    "chars": 3456,
    "preview": "# Motivation\n\n!!! quote\n    **Django Ninja** looks basically the same as **FastAPI**, so why not just use FastAPI?\n\nInde"
  },
  {
    "path": "docs/docs/proposals/cbv.md",
    "chars": 4697,
    "preview": "# Class Based Operations\n\n\n!!! warning \"\"\n    This is just a proposal and it is **not present in library code**, but eve"
  },
  {
    "path": "docs/docs/proposals/index.md",
    "chars": 460,
    "preview": "# Enhancement Proposals\n\nEnhancement Proposals are a formal way of proposing large feature additions to the **Django Nin"
  },
  {
    "path": "docs/docs/proposals/v1.md",
    "chars": 912,
    "preview": "# Potential v1 changes\n\nDjango Ninja is already used by tens of companies and by the visitors and downloads stats it's g"
  },
  {
    "path": "docs/docs/reference/api.md",
    "chars": 110,
    "preview": "# NinjaAPI\n\n::: ninja.main.NinjaAPI\n    rendering:\n      show_signature: False\n      group_by_category: False\n"
  },
  {
    "path": "docs/docs/reference/csrf.md",
    "chars": 4208,
    "preview": "# CSRF\n\n## What is CSRF?\n> [Cross Site Request Forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery) occurs"
  },
  {
    "path": "docs/docs/reference/management-commands.md",
    "chars": 307,
    "preview": "# Management Commands\n\nManagement commands require **Django Ninja** to be installed in Django's\n`INSTALLED_APPS` setting"
  },
  {
    "path": "docs/docs/reference/operations-parameters.md",
    "chars": 6706,
    "preview": "# Operations parameters\n\n## OpenAPI Schema related\n\nThe following parameters interact with how the OpenAPI schema (and d"
  },
  {
    "path": "docs/docs/reference/settings.md",
    "chars": 115,
    "preview": "# Django Settings\n\n::: ninja.conf.Settings\n    rendering:\n      show_source: False\n      show_root_toc_entry: False"
  },
  {
    "path": "docs/docs/releases.md",
    "chars": 119,
    "preview": "# Release Notes\n\nFollow and subscribe for new releases on GitHub:\n\n<https://github.com/vitalik/django-ninja/releases>\n\n"
  },
  {
    "path": "docs/docs/tutorial/index.md",
    "chars": 1778,
    "preview": "# Tutorial - First Steps\n\nThis tutorial shows you how to use **Django Ninja** with most of its features.\n\nThis tutorial "
  },
  {
    "path": "docs/docs/tutorial/other/crud.md",
    "chars": 7257,
    "preview": "# CRUD example\n\n\n**CRUD**  - **C**reate, **R**etrieve, **U**pdate, **D**elete are the four basic functions of persistent"
  },
  {
    "path": "docs/docs/tutorial/other/video.md",
    "chars": 559,
    "preview": "# Video Tutorials\n\n## Sneaky REST APIs With Django Ninja\n\n[realpython.com/lessons/sneaky-rest-apis-with-django-ninja-ove"
  },
  {
    "path": "docs/docs/tutorial/step2.md",
    "chars": 3445,
    "preview": "# Tutorial - Parsing Input\n\n## Input from the query string\n\nLet's change our operation to accept a name from the URL's q"
  },
  {
    "path": "docs/docs/tutorial/step3.md",
    "chars": 1426,
    "preview": "# Tutorial - Handling Responses\n\n## Define a response Schema\n\n**Django Ninja** allows you to define the schema of your r"
  },
  {
    "path": "docs/docs/whatsnew_v1.md",
    "chars": 5417,
    "preview": "# Welcome to Django Ninja 1.0\n\n\nTo get started install latest version with\n```\npip install -U django-ninja\n```\n\ndjango-n"
  },
  {
    "path": "docs/mkdocs.yml",
    "chars": 3407,
    "preview": "site_name: Django Ninja\nsite_description: Django Ninja - Django REST framework with high performance, easy to learn, fas"
  },
  {
    "path": "docs/requirements.txt",
    "chars": 162,
    "preview": "mkdocs==1.5.3\nmkdocs-autorefs==1.0.1\nmkdocs-material==9.5.4\nmkdocs-material-extensions==1.3.1\nmarkdown-include==0.8.1\nmk"
  },
  {
    "path": "docs/src/index001.py",
    "chars": 274,
    "preview": "from django.contrib import admin\nfrom django.urls import path\nfrom ninja import NinjaAPI\n\napi = NinjaAPI()\n\n\n@api.get(\"/"
  },
  {
    "path": "docs/src/tutorial/authentication/apikey01.py",
    "chars": 442,
    "preview": "from ninja.security import APIKeyQuery\nfrom someapp.models import Client\n\n\nclass ApiKey(APIKeyQuery):\n    param_name = \""
  },
  {
    "path": "docs/src/tutorial/authentication/apikey02.py",
    "chars": 322,
    "preview": "from ninja.security import APIKeyHeader\n\n\nclass ApiKey(APIKeyHeader):\n    param_name = \"X-API-Key\"\n\n    def authenticate"
  },
  {
    "path": "docs/src/tutorial/authentication/apikey03.py",
    "chars": 298,
    "preview": "from ninja.security import APIKeyCookie\n\n\nclass CookieKey(APIKeyCookie):\n    def authenticate(self, request, key):\n     "
  },
  {
    "path": "docs/src/tutorial/authentication/basic01.py",
    "chars": 314,
    "preview": "from ninja.security import HttpBasicAuth\n\n\nclass BasicAuth(HttpBasicAuth):\n    def authenticate(self, request, username,"
  },
  {
    "path": "docs/src/tutorial/authentication/bearer01.py",
    "chars": 271,
    "preview": "from ninja.security import HttpBearer\n\n\nclass AuthBearer(HttpBearer):\n    def authenticate(self, request, token):\n      "
  },
  {
    "path": "docs/src/tutorial/authentication/bearer02.py",
    "chars": 547,
    "preview": "from ninja import NinjaAPI\nfrom ninja.security import HttpBearer\n\napi = NinjaAPI()\n\nclass InvalidToken(Exception):\n    p"
  },
  {
    "path": "docs/src/tutorial/authentication/code001.py",
    "chars": 189,
    "preview": "from ninja import NinjaAPI\nfrom ninja.security import django_auth\n\napi = NinjaAPI()\n\n\n@api.get(\"/pets\", auth=django_auth"
  },
  {
    "path": "docs/src/tutorial/authentication/code002.py",
    "chars": 229,
    "preview": "def ip_whitelist(request):\n    if request.META[\"REMOTE_ADDR\"] == \"8.8.8.8\":\n        return \"8.8.8.8\"\n\n\n@api.get(\"/ipwhit"
  },
  {
    "path": "docs/src/tutorial/authentication/global01.py",
    "chars": 542,
    "preview": "from ninja import NinjaAPI, Form\nfrom ninja.security import HttpBearer\n\n\nclass GlobalAuth(HttpBearer):\n    def authentic"
  },
  {
    "path": "docs/src/tutorial/authentication/multiple01.py",
    "chars": 390,
    "preview": "from ninja.security import APIKeyQuery, APIKeyHeader\n\n\nclass AuthCheck:\n    def authenticate(self, request, key):\n      "
  },
  {
    "path": "docs/src/tutorial/authentication/schema01.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/src/tutorial/body/code01.py",
    "chars": 233,
    "preview": "from typing import Optional\nfrom ninja import Schema\n\n\nclass Item(Schema):\n    name: str\n    description: Optional[str] "
  },
  {
    "path": "docs/src/tutorial/body/code02.py",
    "chars": 255,
    "preview": "from ninja import Schema\n\n\nclass Item(Schema):\n    name: str\n    description: str = None\n    price: float\n    quantity: "
  },
  {
    "path": "docs/src/tutorial/body/code03.py",
    "chars": 272,
    "preview": "from ninja import Schema\n\n\nclass Item(Schema):\n    name: str\n    description: str = None\n    price: float\n    quantity: "
  },
  {
    "path": "docs/src/tutorial/form/code01.py",
    "chars": 207,
    "preview": "from ninja import Form, Schema\n\n\nclass Item(Schema):\n    name: str\n    description: str = None\n    price: float\n    quan"
  },
  {
    "path": "docs/src/tutorial/form/code02.py",
    "chars": 284,
    "preview": "from ninja import Form, Schema\n\n\nclass Item(Schema):\n    name: str\n    description: str = None\n    price: float\n    quan"
  },
  {
    "path": "docs/src/tutorial/form/code03.py",
    "chars": 670,
    "preview": "from ninja import Form, Schema\nfrom typing import Annotated, TypeVar\nfrom pydantic import WrapValidator\nfrom pydantic_co"
  },
  {
    "path": "docs/src/tutorial/path/code01.py",
    "chars": 94,
    "preview": "@api.get(\"/items/{item_id}\")\ndef read_item(request, item_id):\n    return {\"item_id\": item_id}\n"
  },
  {
    "path": "docs/src/tutorial/path/code010.py",
    "chars": 319,
    "preview": "import datetime\nfrom ninja import Schema, Path\n\n\nclass PathDate(Schema):\n    year: int\n    month: int\n    day: int\n\n    "
  },
  {
    "path": "docs/src/tutorial/path/code02.py",
    "chars": 99,
    "preview": "@api.get(\"/items/{item_id}\")\ndef read_item(request, item_id: int):\n    return {\"item_id\": item_id}\n"
  },
  {
    "path": "docs/src/tutorial/query/code01.py",
    "chars": 208,
    "preview": "weapons = [\"Ninjato\", \"Shuriken\", \"Katana\", \"Kama\", \"Kunai\", \"Naginata\", \"Yari\"]\n\n\n@api.get(\"/weapons\")\ndef list_weapons"
  },
  {
    "path": "docs/src/tutorial/query/code010.py",
    "chars": 361,
    "preview": "import datetime\nfrom typing import List\n\nfrom pydantic import Field\n\nfrom ninja import Query, Schema\n\n\nclass Filters(Sch"
  },
  {
    "path": "docs/src/tutorial/query/code02.py",
    "chars": 259,
    "preview": "weapons = [\"Ninjato\", \"Shuriken\", \"Katana\", \"Kama\", \"Kunai\", \"Naginata\", \"Yari\"]\n\n\n@api.get(\"/weapons/search\")\ndef searc"
  },
  {
    "path": "docs/src/tutorial/query/code03.py",
    "chars": 157,
    "preview": "from datetime import date\n\n\n@api.get(\"/example\")\ndef example(request, s: str = None, b: bool = None, d: date = None, i: "
  },
  {
    "path": "mypy.ini",
    "chars": 490,
    "preview": "[mypy]\npython_version = 3.12\n\nshow_column_numbers = True\nshow_error_codes = True\n\nfollow_imports = normal\nignore_missing"
  },
  {
    "path": "ninja/__init__.py",
    "chars": 1162,
    "preview": "\"\"\"Django Ninja - Fast Django REST framework\"\"\"\n\n__version__ = \"1.6.2\"\n\nfrom pydantic import Field\n\nfrom ninja.files imp"
  },
  {
    "path": "ninja/compatibility/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "ninja/compatibility/files.py",
    "chars": 2368,
    "preview": "from typing import Any, List\n\nfrom asgiref.sync import iscoroutinefunction, sync_to_async\nfrom django.conf import settin"
  },
  {
    "path": "ninja/compatibility/streaming.py",
    "chars": 3397,
    "preview": "\"\"\"Compatibility layer for async streaming responses.\n\nDjango 4.2+ supports passing async iterators to StreamingHttpResp"
  },
  {
    "path": "ninja/compatibility/util.py",
    "chars": 1043,
    "preview": "import sys\nfrom typing import Union\n\n__all__ = [\"UNION_TYPES\", \"get_annotations_from_namespace\"]\n\n\n# python3.10+ syntax "
  },
  {
    "path": "ninja/conf.py",
    "chars": 1525,
    "preview": "from math import inf\nfrom typing import Dict, Optional, Set, Tuple\n\nfrom django.conf import settings as django_settings\n"
  },
  {
    "path": "ninja/constants.py",
    "chars": 364,
    "preview": "from typing import Any, Dict, Optional\n\n__all__ = [\"NOT_SET\"]\n\n\nclass NOT_SET_TYPE:\n    def __repr__(self) -> str:  # pr"
  },
  {
    "path": "ninja/decorators.py",
    "chars": 1688,
    "preview": "from functools import partial\nfrom typing import Any, Callable, Tuple\n\nfrom typing_extensions import Literal\n\nfrom ninja"
  },
  {
    "path": "ninja/errors.py",
    "chars": 3706,
    "preview": "import logging\nimport traceback\nfrom functools import partial\nfrom typing import TYPE_CHECKING, Generic, List, Optional,"
  },
  {
    "path": "ninja/files.py",
    "chars": 953,
    "preview": "from typing import Any, Callable, Dict\n\nfrom django.core.files.uploadedfile import UploadedFile as DjangoUploadedFile\nfr"
  },
  {
    "path": "ninja/filter_schema.py",
    "chars": 9632,
    "preview": "import warnings\nfrom typing import Any, List, Optional, TypeVar, Union, cast\n\nfrom django.core.exceptions import Imprope"
  },
  {
    "path": "ninja/main.py",
    "chars": 23517,
    "preview": "from typing import (\n    TYPE_CHECKING,\n    Any,\n    Callable,\n    Dict,\n    List,\n    Optional,\n    Sequence,\n    Tuple"
  },
  {
    "path": "ninja/management/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "ninja/management/commands/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "ninja/management/commands/export_openapi_schema.py",
    "chars": 2948,
    "preview": "import json\nfrom pathlib import Path\nfrom typing import Any, Optional\n\nfrom django.core.management.base import BaseComma"
  },
  {
    "path": "ninja/management/utils.py",
    "chars": 1887,
    "preview": "import textwrap\nfrom typing import Type\n\nfrom django.core.management.base import BaseCommand\n\n\ndef command_docstring(cmd"
  },
  {
    "path": "ninja/openapi/__init__.py",
    "chars": 70,
    "preview": "from ninja.openapi.schema import get_schema\n\n__all__ = [\"get_schema\"]\n"
  },
  {
    "path": "ninja/openapi/docs.py",
    "chars": 3739,
    "preview": "import json\nfrom abc import ABC, abstractmethod\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING, Any, Optional"
  },
  {
    "path": "ninja/openapi/schema.py",
    "chars": 15001,
    "preview": "import itertools\nimport re\nfrom http.client import responses\nfrom typing import TYPE_CHECKING, Any, Dict, Generator, Lis"
  },
  {
    "path": "ninja/openapi/urls.py",
    "chars": 1175,
    "preview": "from functools import partial\nfrom typing import TYPE_CHECKING, Any, List\n\nfrom django.urls import path\n\nfrom .views imp"
  },
  {
    "path": "ninja/openapi/views.py",
    "chars": 942,
    "preview": "from typing import TYPE_CHECKING, Any, NoReturn\n\nfrom django.http import Http404, HttpRequest, HttpResponse\n\nfrom ninja."
  },
  {
    "path": "ninja/operation.py",
    "chars": 26999,
    "preview": "import inspect\nimport warnings\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Callable,\n    Coroutine,\n    Dict,\n "
  },
  {
    "path": "ninja/orm/__init__.py",
    "chars": 194,
    "preview": "from ninja.orm.factory import create_schema\nfrom ninja.orm.fields import register_field\nfrom ninja.orm.metaclass import "
  },
  {
    "path": "ninja/orm/factory.py",
    "chars": 5666,
    "preview": "import itertools\nfrom typing import Any, Dict, Iterator, List, Optional, Set, Tuple, Type, Union, cast\n\nfrom django.db.m"
  },
  {
    "path": "ninja/orm/fields.py",
    "chars": 6421,
    "preview": "import datetime\nfrom decimal import Decimal\nfrom typing import Any, Callable, Dict, List, Tuple, Type, TypeVar, Union, n"
  },
  {
    "path": "ninja/orm/metaclass.py",
    "chars": 4069,
    "preview": "from typing import Any, List, Optional, Union, no_type_check\n\nfrom django.apps import apps\nfrom django.db.models import "
  },
  {
    "path": "ninja/orm/shortcuts.py",
    "chars": 554,
    "preview": "from typing import Any, List, Type\n\nfrom ninja import Schema\nfrom ninja.orm.factory import create_schema\n\n__all__ = [\"S\""
  },
  {
    "path": "ninja/pagination.py",
    "chars": 25392,
    "preview": "import binascii\nimport inspect\nfrom abc import ABC, abstractmethod\nfrom base64 import b64decode, b64encode\nfrom functool"
  },
  {
    "path": "ninja/params/__init__.py",
    "chars": 3375,
    "preview": "from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Pattern, TypeVar, Union\n\nfrom typing_extensions import "
  },
  {
    "path": "ninja/params/functions.py",
    "chars": 7459,
    "preview": "# Yeah, this is a bit strange\n# but the whole point of this module is to make mypy and typehints happy\n# what it basical"
  },
  {
    "path": "ninja/params/models.py",
    "chars": 8039,
    "preview": "from abc import ABC, abstractmethod\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Dict,\n    List,\n    Optional,\n "
  },
  {
    "path": "ninja/parser.py",
    "chars": 710,
    "preview": "import json\nfrom typing import List, cast\n\nfrom django.http import HttpRequest\nfrom django.utils.datastructures import M"
  },
  {
    "path": "ninja/patch_dict.py",
    "chars": 2270,
    "preview": "from typing import (\n    TYPE_CHECKING,\n    Any,\n    Dict,\n    Generic,\n    Optional,\n    Type,\n    TypeVar,\n)\n\nfrom pyd"
  },
  {
    "path": "ninja/py.typed",
    "chars": 1,
    "preview": "\n"
  },
  {
    "path": "ninja/renderers.py",
    "chars": 781,
    "preview": "import json\nfrom typing import Any, Mapping, Optional, Type\n\nfrom django.http import HttpRequest\n\nfrom ninja.responses i"
  },
  {
    "path": "ninja/responses.py",
    "chars": 1777,
    "preview": "from enum import Enum\nfrom ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network\nfrom typing import Any, F"
  },
  {
    "path": "ninja/router.py",
    "chars": 26589,
    "preview": "import re\nfrom dataclasses import dataclass, field\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Callable,\n    Di"
  },
  {
    "path": "ninja/schema.py",
    "chars": 8516,
    "preview": "\"\"\"\nSince \"Model\" word would be very confusing when used in django context, this\nmodule basically makes an alias for it "
  },
  {
    "path": "ninja/security/__init__.py",
    "chars": 577,
    "preview": "from ninja.security.apikey import APIKeyCookie, APIKeyHeader, APIKeyQuery\nfrom ninja.security.http import HttpBasicAuth,"
  },
  {
    "path": "ninja/security/apikey.py",
    "chars": 1906,
    "preview": "from abc import ABC, abstractmethod\nfrom typing import Any, Optional\n\nfrom django.http import HttpRequest\n\nfrom ninja.er"
  },
  {
    "path": "ninja/security/base.py",
    "chars": 1093,
    "preview": "from abc import ABC, abstractmethod\nfrom typing import Any, Optional\n\nfrom django.http import HttpRequest\n\nfrom ninja.er"
  },
  {
    "path": "ninja/security/http.py",
    "chars": 2678,
    "preview": "import logging\nfrom abc import ABC, abstractmethod\nfrom base64 import b64decode\nfrom typing import Any, Optional, Tuple\n"
  },
  {
    "path": "ninja/security/session.py",
    "chars": 1369,
    "preview": "from typing import Any, Optional\n\nfrom django.conf import settings\nfrom django.http import HttpRequest\n\nfrom ninja.secur"
  },
  {
    "path": "ninja/signature/__init__.py",
    "chars": 134,
    "preview": "from ninja.signature.details import ViewSignature\nfrom ninja.signature.utils import is_async\n\n__all__ = [\"ViewSignature\""
  },
  {
    "path": "ninja/signature/details.py",
    "chars": 15312,
    "preview": "import inspect\nimport warnings\nfrom collections import defaultdict, namedtuple\nfrom sys import version_info\nfrom typing "
  },
  {
    "path": "ninja/signature/utils.py",
    "chars": 2844,
    "preview": "import asyncio\nimport inspect\nimport re\nfrom sys import version_info\nfrom typing import Any, Callable, ForwardRef, List,"
  },
  {
    "path": "ninja/static/ninja/redoc.standalone.js",
    "chars": 938649,
    "preview": "/*! For license information please see redoc.standalone.js.LICENSE.txt */\n!function(e,t){\"object\"==typeof exports&&\"obje"
  },
  {
    "path": "ninja/static/ninja/swagger-ui-bundle.js",
    "chars": 1509147,
    "preview": "/*! For license information please see swagger-ui-bundle.js.LICENSE.txt */\n!function webpackUniversalModuleDefinition(s,"
  },
  {
    "path": "ninja/static/ninja/swagger-ui-init.js",
    "chars": 1308,
    "preview": "/**JS file for handling the SwaggerUIBundle and avoid inline script */\nconst csrfSettings = document.querySelector(\"body"
  },
  {
    "path": "ninja/static/ninja/swagger-ui.css",
    "chars": 177182,
    "preview": ".swagger-ui{color:#3b4151;font-family:sans-serif}.swagger-ui html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-tex"
  },
  {
    "path": "ninja/streaming.py",
    "chars": 2046,
    "preview": "import json\nfrom typing import Any, Dict\n\nfrom ninja.responses import NinjaJSONEncoder\n\n__all__ = [\"StreamFormat\", \"SSE\""
  },
  {
    "path": "ninja/templates/ninja/favicons.html",
    "chars": 216,
    "preview": "{% load static %}\n\n{% block favicons %}\n    <link rel=\"icon\" href=\"{% static 'ninja/favicon.svg' %}\" type=\"image/svg+xml"
  },
  {
    "path": "ninja/templates/ninja/redoc.html",
    "chars": 803,
    "preview": "{% load static %}\n<!DOCTYPE html>\n<html>\n<head>\n    {% include \"ninja/favicons.html\" %}\n    <title>{{ api.title }}</titl"
  },
  {
    "path": "ninja/templates/ninja/redoc_cdn.html",
    "chars": 947,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n    <link rel=\"icon\" href=\"https://django-ninja.dev/img/favicon.svg\" type=\"image/svg+xml\">"
  },
  {
    "path": "ninja/templates/ninja/swagger.html",
    "chars": 650,
    "preview": "{% load static %}\n<!DOCTYPE html>\n<html>\n<head>\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"{% static 'ninja/swagge"
  },
  {
    "path": "ninja/templates/ninja/swagger_cdn.html",
    "chars": 1220,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/swagger-ui-d"
  },
  {
    "path": "ninja/testing/__init__.py",
    "chars": 106,
    "preview": "from ninja.testing.client import TestAsyncClient, TestClient\n\n__all__ = [\"TestClient\", \"TestAsyncClient\"]\n"
  },
  {
    "path": "ninja/testing/client.py",
    "chars": 8235,
    "preview": "import inspect\nfrom json import dumps as json_dumps\nfrom json import loads as json_loads\nfrom typing import Any, Callabl"
  },
  {
    "path": "ninja/throttling.py",
    "chars": 8218,
    "preview": "import hashlib\nimport time\nfrom typing import Dict, List, Optional, Tuple\n\nfrom django.core.cache import cache as defaul"
  },
  {
    "path": "ninja/types.py",
    "chars": 313,
    "preview": "from typing import Any, Callable, Dict, TypeVar\n\n__all__ = [\"DictStrAny\", \"TCallable\"]\n\nDictStrAny = Dict[str, Any]\n\nTCa"
  },
  {
    "path": "ninja/utils.py",
    "chars": 1836,
    "preview": "import inspect\nfrom typing import Any, Callable, Optional, Type\n\nfrom django.http import HttpRequest, HttpResponseForbid"
  },
  {
    "path": "pyproject.toml",
    "chars": 3097,
    "preview": "[build-system]\nrequires = [\"flit_core >=2,<4\"]\nbuild-backend = \"flit_core.buildapi\"\n\n[tool.flit.metadata]\nmodule = \"ninj"
  },
  {
    "path": "scripts/build-docs.sh",
    "chars": 109,
    "preview": "#!/usr/bin/env bash\nset -x\nset -e\n\npip install -r docs/requirements.txt\n\ncd docs\nPYTHONPATH=../ mkdocs build\n"
  },
  {
    "path": "tests/conftest.py",
    "chars": 367,
    "preview": "import os\nimport sys\nfrom pathlib import Path\n\nROOT = Path(__file__).parent.parent.resolve()\n\nsys.path.insert(0, str(ROO"
  },
  {
    "path": "tests/demo_project/db.sqlite3",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/demo_project/demo/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/demo_project/demo/asgi.py",
    "chars": 425,
    "preview": "\"\"\"\nASGI config for demo project.\n\nIt exposes the ASGI callable as a module-level variable named ``application``.\n\nFor m"
  },
  {
    "path": "tests/demo_project/demo/settings.py",
    "chars": 1609,
    "preview": "from pathlib import Path\n\nBASE_DIR = Path(__file__).parent.parent\n\n\nSECRET_KEY = \"NOT-SUPER-SECRET-DO-NOT-USE-ME\"\n\n\nDEBU"
  },
  {
    "path": "tests/demo_project/demo/urls.py",
    "chars": 986,
    "preview": "from django.contrib import admin\nfrom django.urls import path\n\nfrom ninja import NinjaAPI\n\napi_v1 = NinjaAPI()\napi_v1.ad"
  },
  {
    "path": "tests/demo_project/demo/wsgi.py",
    "chars": 425,
    "preview": "\"\"\"\nWSGI config for demo project.\n\nIt exposes the WSGI callable as a module-level variable named ``application``.\n\nFor m"
  },
  {
    "path": "tests/demo_project/manage.py",
    "chars": 658,
    "preview": "#!/usr/bin/env python\n\"\"\"Django's command-line utility for administrative tasks.\"\"\"\n\nimport os\nimport sys\n\n\ndef main():\n"
  },
  {
    "path": "tests/demo_project/multi_param/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/demo_project/multi_param/api.py",
    "chars": 5503,
    "preview": "\"\"\"Test App to use with Swagger UI and in unit tests\"\"\"\n\nfrom pydantic import ConfigDict\n\nfrom ninja import (\n    Body,\n"
  },
  {
    "path": "tests/demo_project/multi_param/asgi.py",
    "chars": 424,
    "preview": "\"\"\"\nASGI config for multi_param project.\n\nIt exposes the ASGI callable as a module-level variable named ``application``."
  },
  {
    "path": "tests/demo_project/multi_param/manage.py",
    "chars": 701,
    "preview": "#!/usr/bin/env python\n\"\"\"Django's command-line utility for administrative tasks.\"\"\"\n\nimport os\nimport sys\n\n\ndef main():\n"
  },
  {
    "path": "tests/demo_project/multi_param/settings.py",
    "chars": 2190,
    "preview": "\"\"\"\nDjango settings for multi_param project.\n\nGenerated by 'django-admin startproject' using Django 3.1.13.\n\nFor more in"
  },
  {
    "path": "tests/demo_project/multi_param/urls.py",
    "chars": 225,
    "preview": "from django.urls import path\n\nfrom ninja import NinjaAPI\n\nfrom .api import router\n\napi_multi_param = NinjaAPI(version=\"1"
  },
  {
    "path": "tests/demo_project/multi_param/wsgi.py",
    "chars": 424,
    "preview": "\"\"\"\nWSGI config for multi_param project.\n\nIt exposes the WSGI callable as a module-level variable named ``application``."
  },
  {
    "path": "tests/demo_project/someapp/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/demo_project/someapp/admin.py",
    "chars": 29,
    "preview": "# Register your models here.\n"
  },
  {
    "path": "tests/demo_project/someapp/api.py",
    "chars": 836,
    "preview": "from datetime import date\nfrom typing import List\n\nfrom django.shortcuts import get_object_or_404\nfrom pydantic import B"
  },
  {
    "path": "tests/demo_project/someapp/models.py",
    "chars": 495,
    "preview": "from django.db import models\n\n\nclass Category(models.Model):\n    title = models.CharField(max_length=100)\n\n\nclass Event("
  },
  {
    "path": "tests/demo_project/someapp/views.py",
    "chars": 26,
    "preview": "# Create your views here.\n"
  },
  {
    "path": "tests/env-matrix/Dockerfile",
    "chars": 1519,
    "preview": "FROM python:3.8\n\nRUN apt install curl\nRUN curl https://pyenv.run | bash\n\nENV HOME  /root\nENV PYENV_ROOT $HOME/.pyenv\nENV"
  },
  {
    "path": "tests/env-matrix/Dockerfile.backup",
    "chars": 1865,
    "preview": "FROM python:3.8\n\nRUN apt install curl\nRUN curl https://pyenv.run | bash\n\nRUN /root/.pyenv/bin/pyenv install --help\n\nRUN "
  },
  {
    "path": "tests/env-matrix/README.md",
    "chars": 293,
    "preview": "This `env-matrix` speeds up test execution across all environments (Python 3.[6,7,8],  Django2.0,...,3.1)\n\nTo execute\n\n`"
  },
  {
    "path": "tests/env-matrix/create_docker.py",
    "chars": 1136,
    "preview": "PYTHON = [\"3.6.10\", \"3.7.7\", \"3.8.3\"]  # 3.9.0b3\nDJANGO = [\"2.1.15\", \"2.2.12\", \"3.0.6\", \"3.1\"]\n\n\nHEADER = \"\"\"\nFROM pytho"
  },
  {
    "path": "tests/env-matrix/docker-compose.yml",
    "chars": 111,
    "preview": "version: \"3\"\nservices:\n  tester:\n    build:\n      context: ../../\n      dockerfile: tests/env-matrix/Dockerfile"
  },
  {
    "path": "tests/env-matrix/install_env.sh",
    "chars": 245,
    "preview": "#!/bin/bash\n\nPYVER=$1\nDJANGO=$2\nENVNAME=$3\n\neval \"$(pyenv init -)\"\neval \"$(pyenv virtualenv-init -)\"\n\npyenv virtualenv $"
  },
  {
    "path": "tests/env-matrix/run.sh",
    "chars": 132,
    "preview": "#!/bin/bash\n\nENVNAME=$1\n\neval \"$(pyenv init -)\"\neval \"$(pyenv virtualenv-init -)\"\n\necho $ENVNAME\n\npyenv shell $ENVNAME\np"
  },
  {
    "path": "tests/main.py",
    "chars": 8820,
    "preview": "from sys import version_info\nfrom typing import List, Optional\nfrom uuid import UUID\n\nimport pydantic\nimport pytest\nfrom"
  },
  {
    "path": "tests/mypy_test.py",
    "chars": 1144,
    "preview": "# The goal of this file is to test that mypy \"likes\" all the combinations of parametrization\nfrom typing import Any\n\nfro"
  },
  {
    "path": "tests/pytest.ini",
    "chars": 106,
    "preview": "[pytest]\n# python_paths = ./ ./tests/demo_project\naddopts = --nomigrations\n; --ds=demo_project.settings\n\n\n"
  },
  {
    "path": "tests/test_add_decorator.py",
    "chars": 7752,
    "preview": "from functools import wraps\n\nimport pytest\n\nfrom ninja import NinjaAPI, Router\nfrom ninja.testing import TestClient\n\n\n# "
  },
  {
    "path": "tests/test_add_decorator_async.py",
    "chars": 7092,
    "preview": "import asyncio\nfrom functools import wraps\n\nimport pytest\n\nfrom ninja import NinjaAPI, Router\nfrom ninja.testing import "
  },
  {
    "path": "tests/test_alias.py",
    "chars": 964,
    "preview": "from ninja import Field, NinjaAPI, Schema\n\n\nclass SchemaWithAlias(Schema):\n    foo: str = Field(\"\", alias=\"bar\")\n\n\napi ="
  },
  {
    "path": "tests/test_annotated.py",
    "chars": 6462,
    "preview": "from typing import List\n\nfrom typing_extensions import Annotated\nfrom util import pydantic_ref_fix\n\nfrom ninja import Bo"
  },
  {
    "path": "tests/test_api_instance.py",
    "chars": 2006,
    "preview": "import pytest\n\nfrom ninja import NinjaAPI, Router\nfrom ninja.errors import ConfigError\n\n\ndef test_api_instance():\n    \"\""
  },
  {
    "path": "tests/test_app.py",
    "chars": 2980,
    "preview": "import contextlib\nfrom pathlib import Path\nfrom tempfile import NamedTemporaryFile\n\nimport pytest\nfrom django.http impor"
  },
  {
    "path": "tests/test_async.py",
    "chars": 1301,
    "preview": "import asyncio\n\nimport pytest\n\nfrom ninja import NinjaAPI\nfrom ninja.security import APIKeyQuery\nfrom ninja.testing impo"
  },
  {
    "path": "tests/test_auth.py",
    "chars": 10520,
    "preview": "from unittest.mock import Mock\n\nimport pytest\nfrom django.utils.asyncio import async_unsafe\n\nfrom ninja import NinjaAPI\n"
  },
  {
    "path": "tests/test_auth_async.py",
    "chars": 4489,
    "preview": "import asyncio\n\nimport pytest\n\nfrom ninja import NinjaAPI\nfrom ninja.security import APIKeyQuery, HttpBearer\nfrom ninja."
  },
  {
    "path": "tests/test_auth_global.py",
    "chars": 2517,
    "preview": "from ninja import NinjaAPI, Router\nfrom ninja.security import APIKeyQuery\nfrom ninja.testing import TestClient\n\n\nclass K"
  },
  {
    "path": "tests/test_auth_inheritance_routers.py",
    "chars": 1845,
    "preview": "import pytest\n\nfrom ninja import NinjaAPI, Router\nfrom ninja.security import APIKeyQuery\nfrom ninja.testing import TestC"
  },
  {
    "path": "tests/test_auth_routers.py",
    "chars": 1220,
    "preview": "import pytest\n\nfrom ninja import NinjaAPI, Router\nfrom ninja.security import APIKeyQuery\nfrom ninja.testing import TestC"
  },
  {
    "path": "tests/test_body.py",
    "chars": 3446,
    "preview": "from typing import Any, Dict, List\n\nimport pytest\nfrom pydantic import field_validator\n\nfrom ninja import Body, Form, Ni"
  },
  {
    "path": "tests/test_compatibility.py",
    "chars": 1778,
    "preview": "\"\"\"Test Python 3.14 compatibility for ModelSchema annotations.\n\nPython 3.14 no longer puts __annotations__ in the class "
  },
  {
    "path": "tests/test_conf.py",
    "chars": 196,
    "preview": "from ninja.conf import settings\n\n\ndef test_default_configuration():\n    assert settings.PAGINATION_CLASS == \"ninja.pagin"
  },
  {
    "path": "tests/test_csrf.py",
    "chars": 7838,
    "preview": "import re\n\nfrom django.conf import settings\nfrom django.http import JsonResponse\nfrom django.views.decorators.csrf impor"
  }
]

// ... and 79 more files (download for full content)

About this extraction

This page contains the full source code of the vitalik/django-ninja GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 279 files (3.4 MB), approximately 895.9k tokens, and a symbol index with 6169 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!