Full Code of natenho/Mockaco for AI

master 168cbbe5663d cached
215 files
312.2 KB
79.1k tokens
443 symbols
1 requests
Download .txt
Showing preview only (367K chars total). Download the full file or copy to clipboard to get everything.
Repository: natenho/Mockaco
Branch: master
Commit: 168cbbe5663d
Files: 215
Total size: 312.2 KB

Directory structure:
gitextract_rnbuvyzp/

├── .dockerignore
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── 01_feature_request.yml
│   │   ├── 02_bug_report.yml
│   │   └── config.yml
│   ├── PULL_REQUEST_TEMPLATE/
│   │   └── pull_request_template.md
│   └── workflows/
│       ├── main-release.yml
│       ├── website-deploy-test.yml
│       └── website-deploy.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── Mockaco.sln
├── README.md
├── appveyor.yml
├── checkBuild.ps1
├── src/
│   ├── Mockaco/
│   │   ├── .dockerignore
│   │   ├── Docker/
│   │   │   ├── Dockerfile
│   │   │   └── README.md
│   │   ├── Extensions/
│   │   │   └── CommandLineExtensions.cs
│   │   ├── Mockaco.csproj
│   │   ├── Mocks/
│   │   │   └── hello.json
│   │   ├── Program.cs
│   │   ├── Properties/
│   │   │   ├── PublishProfiles/
│   │   │   │   └── FolderProfile.pubxml
│   │   │   └── launchSettings.json
│   │   ├── Settings/
│   │   │   ├── appsettings.Development.json
│   │   │   ├── appsettings.Docker.json
│   │   │   ├── appsettings.Production.json
│   │   │   └── appsettings.json
│   │   ├── Startup.Banner.cs
│   │   └── Startup.cs
│   └── Mockaco.AspNetCore/
│       ├── Chaos/
│       │   └── Strategies/
│       │       ├── ChaosStrategyBehavior.cs
│       │       ├── ChaosStrategyException.cs
│       │       ├── ChaosStrategyLatency.cs
│       │       ├── ChaosStrategyResult.cs
│       │       ├── ChaosStrategyTimeout.cs
│       │       └── IChaosStrategy.cs
│       ├── Common/
│       │   ├── HttpContentTypes.cs
│       │   ├── HttpHeaders.cs
│       │   ├── InvalidMockException.cs
│       │   ├── RouteMatcher.cs
│       │   ├── SimpleExceptionConverter.cs
│       │   └── StringDictionary.cs
│       ├── DependencyInjection/
│       │   ├── MockacoApplicationBuilder.cs
│       │   └── MockacoServiceCollection.cs
│       ├── Extensions/
│       │   ├── EnumerableExtensions.cs
│       │   ├── HttpRequestExtensions.cs
│       │   ├── ObjectExtensions.cs
│       │   ├── StringDictionaryExtensions.cs
│       │   └── StringExtensions.cs
│       ├── HealthChecks/
│       │   └── StartupHealthCheck.cs
│       ├── IMockProvider.cs
│       ├── IMockacoContext.cs
│       ├── InternalsVisibleTo.cs
│       ├── Middlewares/
│       │   ├── CallbackMiddleware.cs
│       │   ├── ChaosMiddleware.cs
│       │   ├── ErrorHandlingMiddleware.cs
│       │   ├── RequestMatchingMiddleware.cs
│       │   ├── ResponseDelayMiddleware.cs
│       │   └── ResponseMockingMiddleware.cs
│       ├── MockProvider.cs
│       ├── Mockaco.AspNetCore.csproj
│       ├── MockacoContext.cs
│       ├── Options/
│       │   ├── ChaosOptions.cs
│       │   ├── MockacoOptions.cs
│       │   └── TemplateFileProviderOptions.cs
│       ├── Plugins/
│       │   └── PhoneNumberExtensions.cs
│       ├── PublicAPI.Shipped.txt
│       ├── PublicAPI.Unshipped.txt
│       ├── Settings/
│       │   └── VerificationRouteValueTransformer.cs
│       ├── Templating/
│       │   ├── Generating/
│       │   │   ├── Cli/
│       │   │   │   └── GeneratorRunner.cs
│       │   │   ├── GeneratedTemplate.cs
│       │   │   ├── GeneratingOptions.cs
│       │   │   ├── Providers/
│       │   │   │   ├── GeneratedTemplateProviderFactory.cs
│       │   │   │   ├── IGeneratedTemplateProvider.cs
│       │   │   │   ├── IGeneratedTemplateProviderFactory.cs
│       │   │   │   └── OpenApiTemplateProvider.cs
│       │   │   ├── ServiceCollectionExtensions.cs
│       │   │   ├── Source/
│       │   │   │   ├── HttpContentProvider.cs
│       │   │   │   ├── ISourceContentProvider.cs
│       │   │   │   ├── LocalFileContentProvider.cs
│       │   │   │   └── SourceContentProviderComposite.cs
│       │   │   ├── Store/
│       │   │   │   ├── GeneratedTemplateStore.cs
│       │   │   │   ├── IGeneratedTemplateStore.cs
│       │   │   │   └── TemplateStoreOptions.cs
│       │   │   └── TemplatesGenerator.cs
│       │   ├── ITemplateTransformer.cs
│       │   ├── Models/
│       │   │   ├── CallbackTemplate.cs
│       │   │   ├── Error.cs
│       │   │   ├── IRawTemplate.cs
│       │   │   ├── Mock.cs
│       │   │   ├── RawTemplate.cs
│       │   │   ├── RequestTemplate.cs
│       │   │   ├── ResponseTemplate.cs
│       │   │   └── Template.cs
│       │   ├── Providers/
│       │   │   ├── ITemplateProvider.cs
│       │   │   └── TemplateFileProvider.cs
│       │   ├── Request/
│       │   │   ├── FormRequestBodyStrategy.cs
│       │   │   ├── IRequestBodyFactory.cs
│       │   │   ├── IRequestBodyStrategy.cs
│       │   │   ├── IRequestMatcher.cs
│       │   │   ├── JsonRequestBodyStrategy.cs
│       │   │   ├── RequestBodyFactory.cs
│       │   │   ├── RequestConditionMatcher.cs
│       │   │   ├── RequestMethodMatcher.cs
│       │   │   ├── RequestRouteMatcher.cs
│       │   │   └── XmlRequestBodyStrategy.cs
│       │   ├── Response/
│       │   │   ├── BinaryResponseBodyStrategy.cs
│       │   │   ├── DefaultResponseBodyStrategy.cs
│       │   │   ├── IResponseBodyFactory.cs
│       │   │   ├── IResponseBodyStrategy.cs
│       │   │   ├── JsonResponseBodyStrategy.cs
│       │   │   ├── ResponseBodyFactory.cs
│       │   │   ├── StringResponseBodyStrategy.cs
│       │   │   └── XmlResponseBodyStrategy.cs
│       │   ├── Scripting/
│       │   │   ├── IFakerFactory.cs
│       │   │   ├── IGlobalVarialeStorage.cs
│       │   │   ├── IScriptContext.cs
│       │   │   ├── IScriptRunnerFactory.cs
│       │   │   ├── LocalizedFakerFactory.cs
│       │   │   ├── ScriptContext.cs
│       │   │   ├── ScriptContextGlobalVariableStorage.cs
│       │   │   ├── ScriptContextRequest.cs
│       │   │   ├── ScriptContextResponse.cs
│       │   │   └── ScriptRunnerFactory.cs
│       │   ├── T4/
│       │   │   ├── TemplateSegment.cs
│       │   │   └── Tokeniser.cs
│       │   └── TemplateTransformer.cs
│       ├── Verifyer/
│       │   └── VerifyerExtensions.cs
│       └── WarmUps/
│           └── MockProviderWarmUp.cs
├── test/
│   ├── Mockaco.AspNetCore.Tests/
│   │   ├── Common/
│   │   │   └── StringDictionaryTest.cs
│   │   ├── Extensions/
│   │   │   ├── EnumerableExtensionTests.cs
│   │   │   └── StringExtensionsTests.cs
│   │   ├── Middlewares/
│   │   │   ├── CallbackMiddlewareTest.cs
│   │   │   ├── ErrorHandlingMiddlewareTest.cs
│   │   │   ├── RequestMatchingMiddlewareTest.cs
│   │   │   ├── ResponseDelayMiddlewareTest.cs
│   │   │   └── ResponseMockingMiddlewareTest.cs
│   │   ├── Mockaco.AspNetCore.Tests.csproj
│   │   ├── Templating/
│   │   │   ├── Request/
│   │   │   │   ├── JsonRequestBodyStrategyTest.cs
│   │   │   │   └── RequestConditionMatcherTest.cs
│   │   │   ├── Response/
│   │   │   │   ├── BinaryResponseBodyStrategyTest.cs
│   │   │   │   ├── DefaultResponseBodyStrategyTest.cs
│   │   │   │   ├── JsonResponseBodyStrategyTest.cs
│   │   │   │   ├── ResponseBodyFactoryTest.cs
│   │   │   │   └── XmlResponseBodyStrategyTest.cs
│   │   │   ├── Scripting/
│   │   │   │   ├── LocalizedFakerFactoryTest.cs
│   │   │   │   └── ScriptRunnerFactoryTest.cs
│   │   │   ├── TemplateTransformerTest.cs
│   │   │   ├── Transforms_Plain_Json_Template.json
│   │   │   └── Transforms_Scripted_Json_Template.json
│   │   ├── TextFileDataAttribute.cs
│   │   └── Usings.cs
│   └── _postman/
│       └── Mockaco.postman_collection.json
└── website/
    ├── .gitignore
    ├── README.md
    ├── babel.config.js
    ├── blog/
    │   └── authors.yml
    ├── docs/
    │   ├── chaos/
    │   │   └── index.md
    │   ├── configuration/
    │   │   ├── _category_.json
    │   │   └── index.md
    │   ├── generator/
    │   │   ├── _category_.json
    │   │   └── index.md
    │   ├── guides/
    │   │   ├── _category_.json
    │   │   ├── mocking-raw.md
    │   │   ├── mocking-stateful.md
    │   │   └── mocking-xml.md
    │   ├── health-checks/
    │   │   ├── _category_.json
    │   │   └── index.md
    │   ├── quick-start/
    │   │   ├── _category_.json
    │   │   ├── create-mock.md
    │   │   ├── install-run.md
    │   │   └── test-mock.md
    │   ├── reference-scripting/
    │   │   ├── _category_.json
    │   │   ├── faker.md
    │   │   ├── global.md
    │   │   ├── index.md
    │   │   ├── request.md
    │   │   └── response.md
    │   ├── reference-template/
    │   │   ├── _category_.json
    │   │   ├── callback/
    │   │   │   ├── _category_.json
    │   │   │   ├── body-attribute.md
    │   │   │   ├── delay-attribute.md
    │   │   │   ├── headers-attribute.md
    │   │   │   ├── method-attribute.md
    │   │   │   ├── timeout-attribute.md
    │   │   │   └── url-attribute.md
    │   │   ├── request/
    │   │   │   ├── _category_.json
    │   │   │   ├── condition-attribute.md
    │   │   │   ├── method-attribute.md
    │   │   │   └── route-attribute.md
    │   │   └── response/
    │   │       ├── _category_.json
    │   │       ├── body-attribute.md
    │   │       ├── delay-attribute.md
    │   │       ├── file-attribute.md
    │   │       ├── headers-attribute.md
    │   │       ├── indented-attribute.md
    │   │       └── status-attribute.md
    │   ├── request-matching/
    │   │   ├── _category_.json
    │   │   └── index.md
    │   └── verification/
    │       ├── _category_.json
    │       └── index.md
    ├── docusaurus.config.js
    ├── package.json
    ├── sidebars.js
    ├── src/
    │   ├── components/
    │   │   └── HomepageFeatures/
    │   │       ├── index.js
    │   │       └── styles.module.css
    │   ├── css/
    │   │   └── custom.css
    │   └── pages/
    │       ├── index.js
    │       ├── index.module.css
    │       ├── videos.js
    │       └── videos.module.css
    └── static/
        └── .nojekyll

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

================================================
FILE: .dockerignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# DNX
project.lock.json
project.fragment.lock.json
artifacts/

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
**/nupkg/*
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Mockaco-specific
**/.dockerignore
**/*.md
.github/
nupkg/
test/
website/
**/*.log
src/Mockaco/Mocks*/**/*.*
!src/Mockaco/Mocks/hello.json

================================================
FILE: .editorconfig
================================================
[*.{cs,vb}]
dotnet_naming_rule.private_members_with_underscore.symbols  = private_fields
dotnet_naming_rule.private_members_with_underscore.style    = prefix_underscore
dotnet_naming_rule.private_members_with_underscore.severity = suggestion

dotnet_naming_symbols.private_fields.applicable_kinds           = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private

dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _

================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following 
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
# 
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the 
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain


================================================
FILE: .github/ISSUE_TEMPLATE/01_feature_request.yml
================================================
---
name: 🚀 Feature request
description: Suggest an idea for this project
labels: ["enhancement"]
body:
  - type: checkboxes
    id: prerequisites
    attributes:
      label: Prerequisites
      options:
        - label: I have written a descriptive issue title
          required: true
        - label: I have searched existing issues to ensure a similar issue has not already been created
          required: true

  - type: textarea
    id: context
    attributes:
      label: Description
      description: Is your feature request related to a problem? Please describe.
      placeholder: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
    validations:
      required: true

  - type: textarea
    id: proposed_solution
    attributes:
      label: Proposed solution
      description: Describe the solution you'd like.
      placeholder: A clear and concise description of what you want to happen.
    validations:
      required: true

  - type: textarea
    id: alternatives
    attributes:
      label: Alternatives
      description: Describe alternatives you've considered.
      placeholder: A clear and concise description of any alternative solutions or features you've considered.
    validations:
      required: true

  - type: textarea
    id: additional_context
    attributes:
      label: Additional context
      description: Add any other context or screenshots about the feature request here.
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/02_bug_report.yml
================================================
---
name: 🐛 Bug report
description: Create a report to help us improve
labels: ["bug"]
body:
  - type: checkboxes
    id: prerequisites
    attributes:
      label: Prerequisites
      options:
        - label: I have written a descriptive issue title
          required: true
        - label: I have searched existing bugs to ensure a similar bug has not already been created
          required: true

  - type: textarea
    id: description
    attributes:
      label: Description
      description: A clear and concise description of what the bug is.
    validations:
      required: true

  - type: textarea
    id: steps_to_reproduce
    attributes:
      label: Steps to reproduce
      description: You can attach the mock reproducing the wrong behavior or even the configuration files you are using.
    validations:
      required: true

  - type: textarea
    id: expected_behavior
    attributes:
      label: Expected behavior
      description: A clear and concise description of what you expected to happen.
    validations:
      required: true

  - type: textarea
    id: screenshots
    attributes:
      label: Screenshots
      description: If applicable, add screenshots to help explain your problem.
    validations:
      required: false

  - type: textarea
    id: additional_context
    attributes:
      label: Additional context
      description: Add any other context about the problem here.
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false


================================================
FILE: .github/PULL_REQUEST_TEMPLATE/pull_request_template.md
================================================
*Thank you for your contribution to the Mockaco 🐵 repo!*

Before submitting this PR, please make sure:

- [ ] There is an open issue related to your change
- [ ] There aren't other open pull request for the same update/change
- [ ] You have followed the project guidelines
- [ ] Your code builds clean without any errors or warnings
- [ ] You have added unit tests

Please provide a description of your changes and why you'd like us to include them.


================================================
FILE: .github/workflows/main-release.yml
================================================
name: Main Release

on:
  workflow_dispatch:
  push:
    branches:
      - master
  pull_request:
    branches:
      - '**'

env:
  DOCKER_HUB_USERNAME: natenho

jobs:
  build:
    runs-on: ubuntu-latest
    if: "!contains(github.event.head_commit.message, 'skip-ci')"
    steps:
      - name: Checkout code
        uses: actions/checkout@v1
        with:
          fetch-depth: 0
      - name: Setup .NET
        uses: actions/setup-dotnet@v1
        with:
          dotnet-version: '6.0.x'
      - name: Setup GitVersion
        uses: gittools/actions/gitversion/setup@v0.9.7
        with:
          versionSpec: '5.x'
      - name: Determine version
        id: gitversion
        uses: gittools/actions/gitversion/execute@v0.9.7
      - name: Restore dependencies
        run: dotnet restore --verbosity normal
      - name: Build
        run: dotnet build --configuration Release --verbosity normal src/Mockaco/Mockaco.csproj
      - name: Test
        run: dotnet test --configuration Release --verbosity normal test/Mockaco.AspNetCore.Tests/Mockaco.AspNetCore.Tests.csproj
      - name: Bump version and push tag
        if: "github.ref == 'refs/heads/master' && !contains(github.event.head_commit.message, 'skip-release')"
        id: tag_version
        uses: mathieudutour/github-tag-action@v5.6
        with:
          custom_tag: ${{ steps.gitversion.outputs.semVer }}
          github_token: ${{ secrets.GITHUB_TOKEN }}
      - name: Create a GitHub release
        if: "github.ref == 'refs/heads/master'"
        id: github_release
        uses: ncipollo/release-action@v1
        with:
          tag: v${{ steps.gitversion.outputs.semVer }}
          name: v${{ steps.gitversion.outputs.semVer }}
          body: ${{ steps.tag_version.outputs.changelog }}
      - name: Create nupkg
        run: dotnet pack --configuration Nuget --output ./nupkg
      - name: Publish nupkg
        if: "github.ref == 'refs/heads/master' && !contains(github.event.head_commit.message, 'skip-nuget')"
        run: dotnet nuget push **/*.nupkg --api-key ${{secrets.NUGET_AUTH_TOKEN}} --source https://api.nuget.org/v3/index.json --skip-duplicate
      - name: Cache Docker layers
        uses: actions/cache@v4
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-
      - name: Login to Docker Hub
        uses: docker/login-action@v1
        if: "github.ref == 'refs/heads/master'"
        with:
          username: ${{ env.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      - name: Setup Docker Build
        id: buildx
        uses: docker/setup-buildx-action@v2
      - name: Docker Build
        id: docker_build
        uses: docker/build-push-action@v2
        with:
          context: ./
          file: ./src/Mockaco/Docker/Dockerfile
          push: ${{ github.ref == 'refs/heads/master' && !contains(github.event.head_commit.message, 'skip-docker') }}
          tags: ${{ env.DOCKER_HUB_USERNAME }}/mockaco:latest,${{ env.DOCKER_HUB_USERNAME }}/mockaco:${{ steps.gitversion.outputs.semVer }}
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache
          platforms: linux/amd64,linux/arm64
      - name: Docker Image digest
        run: echo ${{ steps.docker_build.outputs.digest }}


================================================
FILE: .github/workflows/website-deploy-test.yml
================================================
name: Deploy to GitHub Pages (Test)

on:
  pull_request:
    branches:
      - master

defaults:
  run:
    working-directory: ./website

jobs:
  test-deploy:
    name: Test deployment
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: yarn
          cache-dependency-path: '**/yarn.lock'

      - name: Install dependencies
        run: yarn install --frozen-lockfile
      - name: Test build website
        run: yarn build

================================================
FILE: .github/workflows/website-deploy.yml
================================================
name: Deploy to GitHub Pages

on:
  push:
    branches:
      - master
    # Review gh actions docs if you want to further define triggers, paths, etc
    # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on

defaults:
  run:
    working-directory: ./website

jobs:
  deploy:
    name: Deploy to GitHub Pages
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: yarn
          cache-dependency-path: '**/yarn.lock'

      - name: Install dependencies
        run: yarn install --frozen-lockfile
      - name: Build website
        run: yarn build

      # Popular action to deploy to GitHub Pages:
      # Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          # Build output to publish to the `gh-pages` branch:
          publish_dir: ./website/build
          # The following lines assign commit authorship to the official
          # GH-Actions bot for deploys to `gh-pages` branch:
          # https://github.com/actions/checkout/issues/13#issuecomment-724415212
          # The GH actions bot is used by default if you didn't specify the two fields.
          # You can swap them out with your own user credentials.
          user_name: github-actions[bot]
          user_email: 41898282+github-actions[bot]@users.noreply.github.com

================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# DNX
project.lock.json
project.fragment.lock.json
artifacts/

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
**/nupkg/*
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Mock Files
src/Mockaco/Mocks*/**/*.*
!src/Mockaco/Mocks/hello.json
/.vscode


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
 advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
 address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
 professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at natenho@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq


================================================
FILE: CONTRIBUTING.md
================================================
## How to contribute to Mockaco

It's great you're reading this, because we need volunteer developers to help this project to move on!

Please take care of reading existent code to follow the same conventions and use clean code intentions when writing new code. Consider the people who will read your code, and make it look nice for them :-).

#### **Did you find a bug?**

* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/natenho/mockaco/issues).

* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/natenho/mockaco/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **mock template** or an **executable test case** demonstrating the expected behavior that is not occurring.

#### **Did you write a patch that fixes a bug?**

* Open a new GitHub pull request with the patch.

* Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.

#### **Do you intend to add a new feature or change an existing one?**

* Please [open a new issue](https://github.com/natenho/mockaco/issues/new) describing the feature so it can be discussed before you start writing it.

#### **Do you have any other questions?**

* Simply [open a new issue](https://github.com/natenho/mockaco/issues/new).

Thanks!

Mockaco Team 🐵



================================================
FILE: LICENSE
================================================
   Mockaco - Copyright (c) 2019-2021 Renato Lima

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this source code except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
   
   --
   
   Serilog is copyright © 2013-2020 Serilog Contributors   
   All Rights Reserved
   
   xUnit Copyright (c) .NET Foundation and Contributors
   All Rights Reserved
   
   Fluent Assertions © 2021 Dennis Doomen      
   
   --
   
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS   

   --
  
   The MIT License (MIT)
   
   MAB.DotIgnore - Copyright (c) 2016 Mark Ashley Bell
   Bogus - Copyright (c) 2015 Brian Chavez
   GitVersion - Copyright (c) 2013 NServiceBus Ltd
   Moq - Copyright (c) Daniel Cazzulino and Contributors
   Newtonsoft.Json - Copyright (c) 2007 James Newton-King
   
   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.
   
   --
        
   New BSD License
   
   Polly - Copyright (c) 2015-2020, App vNext   
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
       * Redistributions of source code must retain the above copyright
         notice, this list of conditions and the following disclaimer.
       * Redistributions in binary form must reproduce the above copyright
         notice, this list of conditions and the following disclaimer in the
         documentation and/or other materials provided with the distribution.
       * Neither the name of App vNext nor the
         names of its contributors may be used to endorse or promote products
         derived from this software without specific prior written permission.
   
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

================================================
FILE: Mockaco.sln
================================================

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32210.238
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mockaco", "src\Mockaco\Mockaco.csproj", "{8BAA1EC5-0BF5-4DA2-87F7-ED0C7B652517}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3F7B6722-59F1-4943-8D45-94D42CE49639}"
	ProjectSection(SolutionItems) = preProject
		README.md = README.md
	EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mockaco.AspNetCore.Tests", "test\Mockaco.AspNetCore.Tests\Mockaco.AspNetCore.Tests.csproj", "{EE57B1B4-29D2-4AE3-8F23-5E622302C30F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mockaco.AspNetCore", "src\Mockaco.AspNetCore\Mockaco.AspNetCore.csproj", "{7766C592-9887-4162-8B9C-51003ED30335}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Nuget|Any CPU = Nuget|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{8BAA1EC5-0BF5-4DA2-87F7-ED0C7B652517}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{8BAA1EC5-0BF5-4DA2-87F7-ED0C7B652517}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{8BAA1EC5-0BF5-4DA2-87F7-ED0C7B652517}.Nuget|Any CPU.ActiveCfg = Nuget|Any CPU
		{8BAA1EC5-0BF5-4DA2-87F7-ED0C7B652517}.Nuget|Any CPU.Build.0 = Nuget|Any CPU
		{8BAA1EC5-0BF5-4DA2-87F7-ED0C7B652517}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{8BAA1EC5-0BF5-4DA2-87F7-ED0C7B652517}.Release|Any CPU.Build.0 = Release|Any CPU
		{EE57B1B4-29D2-4AE3-8F23-5E622302C30F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{EE57B1B4-29D2-4AE3-8F23-5E622302C30F}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{EE57B1B4-29D2-4AE3-8F23-5E622302C30F}.Nuget|Any CPU.ActiveCfg = Release|Any CPU
		{EE57B1B4-29D2-4AE3-8F23-5E622302C30F}.Release|Any CPU.ActiveCfg = Debug|Any CPU
		{7766C592-9887-4162-8B9C-51003ED30335}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{7766C592-9887-4162-8B9C-51003ED30335}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{7766C592-9887-4162-8B9C-51003ED30335}.Nuget|Any CPU.ActiveCfg = Release|Any CPU
		{7766C592-9887-4162-8B9C-51003ED30335}.Nuget|Any CPU.Build.0 = Release|Any CPU
		{7766C592-9887-4162-8B9C-51003ED30335}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{7766C592-9887-4162-8B9C-51003ED30335}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {CABB6019-182D-4F69-834A-5CF7921C290F}
	EndGlobalSection
EndGlobal


================================================
FILE: README.md
================================================
<p align="center">
    <img src="https://github.com/natenho/Mockaco/raw/master/src/Mockaco/Resources/mockaco-logo.svg" width="96px" height="96px" alt="Mockaco">
</p>

# Mockaco

[![Main Build](https://github.com/natenho/Mockaco/actions/workflows/main-release.yml/badge.svg)](https://github.com/natenho/Mockaco/actions/workflows/main-release.yml) [![Docker Pulls](https://img.shields.io/docker/pulls/natenho/mockaco)](https://hub.docker.com/repository/docker/natenho/mockaco) [![Nuget](https://img.shields.io/nuget/dt/Mockaco?color=blue&label=nuget%20downloads)](https://www.nuget.org/packages/Mockaco/) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fnatenho%2FMockaco.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fnatenho%2FMockaco?ref=badge_shield)

Mockaco is an HTTP-based API mock server with fast setup.

## Features

- **Simple JSON-based Configuration**: Configure your mocks easily using a simple JSON format.
- **Pure C# Scripting**: Configure your mocks using C# scripting without the need to learn a new language or API.
- **Delay Simulation**: Simulate network delays to test how your system handles timeouts and latency.
- **Fake Data Generation**: Generate realistic fake data using the built-in functionality.
- **Callback (Webhook) Support**: Trigger another service call when a request hits your mocked API.
- **Verification**: Verify if a specific mock was called during testing to ensure expected interactions.
- **State Support**: Create stateful mocks that return responses based on global variables previously set by other mocks.
- **Portability**: Run the mock server in [any environment supported by .NET](https://github.com/dotnet/core/blob/main/release-notes/6.0/supported-os.md).

## Get Started

Access the documentation on <strong>[natenho.github.io/Mockaco](https://natenho.github.io/Mockaco/)</strong>

[![Mocking APIs with Mockaco | .NET 7](https://user-images.githubusercontent.com/4236481/195997781-b730959e-8d6d-432c-b35a-3adb580abc41.png)](https://www.youtube.com/watch?v=QBnXCgZFzM0 "Mocking APIs with Mockaco | .NET 7")

## License
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fnatenho%2FMockaco.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fnatenho%2FMockaco?ref=badge_large)

---

*Icon made by [Freepik](https://www.freepik.com/ "Freepik") from [www.flaticon.com](https://www.flaticon.com/ "Flaticon") is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/ "Creative Commons BY 3.0")*



================================================
FILE: appveyor.yml
================================================
pull_requests:
  do_not_increment_build_number: true
skip_non_tags: true
image: Visual Studio 2019
configuration: Release
dotnet_csproj:
  patch: true
  file: '**\*.csproj'
  version: '{version}'
  version_prefix: '{version}'
  package_version: '{version}'
  assembly_version: '{version}'
  file_version: '{version}'
  informational_version: '{version}'
build_script:
- cmd: >-
    dotnet --version
    dotnet restore ./src/Mockaco/Mockaco.csproj --verbosity m
    dotnet publish ./src/Mockaco/Mockaco.csproj
test_script:
- cmd: dotnet test .\test\Mockaco.AspNetCore.Tests\Mockaco.AspNetCore.Tests.csproj
artifacts:
- path: src\Mockaco\bin\Release\net5.0\publish\
  name: Mockaco Web Site
deploy:
- provider: GitHub
  tag: v$(appveyor_build_version)
  auth_token:
    secure: ksH+zrtlbEnpy6gasfUkZJQrewTVWVKVFPbzTDmhH94Q2SVBMEc4pI6+6I8JaGuE
  artifact: Mockaco Web Site
  draft: false
  force_update: true
  on:
    APPVEYOR_REPO_TAG: true
- provider: NuGet
  api_key:
    secure: DPYxpk2NINisxfFbRST6aH/m0KBYAt9ETmwkMgxRaGqnKtWlFKaZZFuqXtAG4eSj
  on:
    APPVEYOR_REPO_TAG: true

================================================
FILE: checkBuild.ps1
================================================
dotnet restore --verbosity normal
dotnet build --configuration Release --verbosity normal .\src\Mockaco\Mockaco.csproj
dotnet test --configuration Release --verbosity normal .\test\Mockaco.AspNetCore.Tests\Mockaco.AspNetCore.Tests.csproj
dotnet pack --configuration Nuget --output ./nupkg
docker build -f ./src/Mockaco/Docker/Dockerfile -t mockaco:local .

$containerName = [guid]::NewGuid().ToString()
try {
    docker run --name $containerName -d -p 5000:5000 -v ${PSScriptRoot}/src/Mockaco/Mocks:/app/Mocks mockaco:local
    Start-Sleep -Seconds 5
    docker run --rm -v ${PSScriptRoot}/test/_postman:/etc/newman -t postman/newman:alpine run Mockaco.postman_collection.json
}
finally {
    docker container stop $containerName
    docker container rm $containerName
}


================================================
FILE: src/Mockaco/.dockerignore
================================================
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
/Mocks/*.json
!/Mocks/hello.json

================================================
FILE: src/Mockaco/Docker/Dockerfile
================================================
FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS base
WORKDIR /app
EXPOSE 5000
EXPOSE 5443

FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim AS build

COPY ./src/Mockaco/Mockaco.csproj /src/Mockaco/
COPY ./src/Mockaco.AspNetCore/Mockaco.AspNetCore.csproj /src/Mockaco.AspNetCore/

WORKDIR /src/Mockaco
RUN dotnet restore

WORKDIR /repo
COPY ./ ./

WORKDIR /repo/src/Mockaco
RUN dotnet build "Mockaco.csproj" -c Release -o /app/build
RUN find -iname gitversion.json -exec cat {} \;
RUN dotnet dev-certs https

FROM build AS publish
RUN dotnet publish "Mockaco.csproj" -c Release -o /app/publish

FROM base AS final
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
ENV ASPNETCORE_ENVIRONMENT=Docker
WORKDIR /app

COPY --from=publish /app/publish .
COPY ./src/Mockaco/Mocks/hello.json ./Mocks/
COPY ./src/Mockaco/Settings ./Settings

COPY --from=build /root/.dotnet/corefx/cryptography/x509stores/my /root/.dotnet/corefx/cryptography/x509stores/my

VOLUME /app/Mocks
VOLUME /app/Settings
VOLUME /root/.dotnet/corefx/cryptography/x509stores/my

ENTRYPOINT ["dotnet", "Mockaco.dll"]

================================================
FILE: src/Mockaco/Docker/README.md
================================================
# Quick reference

-	**Where to get help and to file issues**:  
	[GitHub repository](https://github.com/natenho/Mockaco/)

-	**Maintained by**:  
	[natenho](https://github.com/natenho)

# What is Mockaco?

Mockaco is an HTTP-based API mock server with fast setup, featuring:

- Simple JSON-based configuration
- Pure C# scripting - you don't need to learn a new specific language or API to configure your mocks
- Fake data generation - built-in hassle-free fake data generation
- Callback support - trigger another service call when a request hits your mocked API

<img src="https://image.flaticon.com/icons/svg/1574/1574279.svg" width="100px" height="100px" alt="logo">

# How to use this image

## Running the demo

The default image ships with a sample "hello" mock:

```console
$ docker run -it --rm -p 5000:5000 natenho/mockaco
```

Mockaco can be accessed by any HTTP client via `http://localhost:5000`

```console
$ curl -iX GET http://localhost:5000/hello/docker
```
```http
HTTP/1.1 200 OK
Date: Wed, 21 Jun 2019 05:10:00 GMT
Content-Type: application/json
Server: Kestrel
Transfer-Encoding: chunked

{
	"message": "Hello docker!"
}
```

## Running and creating your own mocks

The best way to use the image is by creating a directory on the host system (outside the container) and mount this to the `/app/Mocks` directory inside the container.

1. Create a data directory on a suitable volume on your host system, e.g. `/my/own/mockdir`.
2. Start your `mockaco` container like this:

```console
$ docker run -it --rm -p 5000:80 -v /my/own/mockdir:/app/Mocks natenho/mockaco
```

The `-v /my/own/mockdir:/app/Mocks` part of the command mounts the `/my/own/mockdir` directory from the underlying host system as `/app/Mocks` inside the container, where Mockaco by default will read its mock JSON files.

3. Create a request/response template file named `PingPong.json` under `/my/own/mockdir` folder:

```json
{
  "request": {
	"method": "GET",
	"route": "ping"
  },
  "response": {
	"status": "OK",
	"body": {
	  "response": "pong"
	}
  }
}
```

4. Send a request and get the mocked response, running:

```console
$ curl -iX GET http://localhost:5000/ping
```
```http
HTTP/1.1 200 OK
Date: Wed, 21 Jun 2019 05:10:00 GMT
Content-Type: application/json
Server: Kestrel
Transfer-Encoding: chunked

{
	"response": "pong"
}
```

For advanced usage scenarios, like scripting and fake data generation, refer to the [docs](https://github.com/natenho/Mockaco).

================================================
FILE: src/Mockaco/Extensions/CommandLineExtensions.cs
================================================
namespace System.CommandLine.Parsing
{
    public static class CommandLineExtensions
    {
        public static bool IsUsingCommand(this Parser commandLine, string[] args)
        {
            var parseResult = commandLine.Parse(args);

            return parseResult.CommandResult != parseResult.RootCommandResult;
        }
    }
}


================================================
FILE: src/Mockaco/Mockaco.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk.Web">

	<PropertyGroup>
		<TargetFramework>net6.0</TargetFramework>
		<LangVersion>latest</LangVersion>
		<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
		<DockerfileContext>..\..</DockerfileContext>
		<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
		<Configurations>Debug;Release;Nuget</Configurations>
	</PropertyGroup>

	<PropertyGroup>
		<IsPackable>true</IsPackable>
		<PackAsTool>true</PackAsTool>
		<ToolCommandName>mockaco</ToolCommandName>
		<PackageOutputPath>./nupkg</PackageOutputPath>
		<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
		<Authors>natenho</Authors>
		<Description>HTTP mock server, useful to stub services and simulate dynamic API responses, leveraging ASP.NET Core features, built-in fake data generation and pure C# scripting</Description>
		<PackageProjectUrl>https://github.com/natenho/Mockaco</PackageProjectUrl>
		<RepositoryUrl>https://github.com/natenho/Mockaco</RepositoryUrl>
		<PackageTags>mock http server</PackageTags>
		<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
		<PackageIcon>mockaco-icon.png</PackageIcon>
		<Product>Mockaco</Product>
	</PropertyGroup>

	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
		<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
		<WarningsNotAsErrors></WarningsNotAsErrors>
		<NoWarn>1701;1702;NU5104</NoWarn>
	</PropertyGroup>

	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
		<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
		<WarningsNotAsErrors></WarningsNotAsErrors>
		<NoWarn>1701;1702;NU5104</NoWarn>
	</PropertyGroup>

	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Nuget|AnyCPU'">
		<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
		<WarningsNotAsErrors></WarningsNotAsErrors>
		<NoWarn>1701;1702;NU5104</NoWarn>
	</PropertyGroup>

	<ItemGroup>
		<PackageReference Include="GitVersion.MsBuild" Version="5.12.0">
			<PrivateAssets>all</PrivateAssets>
			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
		</PackageReference>
		<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="6.0.0" />
		<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
		<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
		<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
		<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
		<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
		<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.21308.1" />
	</ItemGroup>

	<ItemGroup Condition="$(Configuration) != 'Debug'">
		<Content Remove="Mocks\**" />
		<None Include="Mocks\hello.json">
			<CopyToOutputDirectory>Always</CopyToOutputDirectory>
		</None>
		<None Include="Resources\mockaco-icon.png">
			<Pack>True</Pack>
			<PackagePath></PackagePath>
		</None>
		<Content Remove="Settings\**" />
		<None Include="Settings\**">
			<CopyToOutputDirectory>Always</CopyToOutputDirectory>
		</None>
	</ItemGroup>

	<ItemGroup>
		<ProjectReference Include="..\Mockaco.AspNetCore\Mockaco.AspNetCore.csproj" />
	</ItemGroup>

</Project>


================================================
FILE: src/Mockaco/Mocks/hello.json
================================================
{
  "request": {
    "method": "GET",
    "route": "hello/{message}"
  },
  "response": {
    "body": {
		"id": "<#= Faker.Random.Guid() #>",
		"message": "Hello <#= Request.Route["message"] #>!",
		"createdAt": <#= JsonConvert.SerializeObject(System.DateTime.Now) #>
	  }
  }
}

================================================
FILE: src/Mockaco/Program.cs
================================================
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Serilog;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Parsing;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection; 

namespace Mockaco
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();

            var commandLine = CreateCommandLineBuilder(args, host)
                .UseDefaults()
                .Build();

            if (commandLine.IsUsingCommand(args))
            {
                await commandLine.InvokeAsync(args);
                return;
            }

            await host.RunAsync();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.ConfigureAppConfiguration((_, configuration) =>
                    {
                        var assemblyLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                        configuration.SetBasePath(Path.Combine(assemblyLocation, "Settings"));

                        var switchMappings = new Dictionary<string, string>() {
                            {"--path", "Mockaco:TemplateFileProvider:Path" },
                            {"--logs", "Serilog:WriteTo:0:Args:path" }
                        };

                        configuration.AddCommandLine(args, switchMappings);
                    })
                    .UseStartup<Startup>();
                })
            .UseSerilog((context, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(context.Configuration));

        private static CommandLineBuilder CreateCommandLineBuilder(string[] args, IHost host)
        {
            var rootCommand = new RootCommand();

            foreach (var cmd in host.Services.GetServices<Command>())
            {
                rootCommand.AddCommand(cmd);
            }

            return new CommandLineBuilder(rootCommand);
        }
    }
}

================================================
FILE: src/Mockaco/Properties/PublishProfiles/FolderProfile.pubxml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121. 
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>FileSystem</WebPublishMethod>
    <PublishProvider>FileSystem</PublishProvider>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <SiteUrlToLaunchAfterPublish />
    <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <ProjectGuid>8baa1ec5-0bf5-4da2-87f7-ed0c7b652517</ProjectGuid>
    <publishUrl>publish</publishUrl>
    <DeleteExistingFiles>True</DeleteExistingFiles>
  </PropertyGroup>
</Project>

================================================
FILE: src/Mockaco/Properties/launchSettings.json
================================================
{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "profiles": {
    "Mockaco": {
      "commandName": "Project",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:5000"
    }
  }
}

================================================
FILE: src/Mockaco/Settings/appsettings.Development.json
================================================
{
  "Mockaco": {
    "TemplateFileProvider": {
      "Path": "Mocks"
    }
  },
  "Serilog": {
    "WriteTo": [
      {
      },
      {
        "Name": "File",
        "Args": {
          "path": "Logs/Mockaco_.log",
          "rollingInterval": "Day",
          "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {RequestId} {Message:lj}{NewLine}{Exception}"
        }
      }
    ]
  }
}

================================================
FILE: src/Mockaco/Settings/appsettings.Docker.json
================================================
{
  "Urls": "http://+:5000;https://+:5443",
  "Mockaco": {
    "TemplateFileProvider": {
      "Path": "Mocks"
    }
  }
}

================================================
FILE: src/Mockaco/Settings/appsettings.Production.json
================================================
{
  "Urls": "http://127.0.0.1:0",
  "Serilog": {
    "WriteTo": [
      {
      },
      {
        "Name": "File",
        "Args": {
          "path": "Logs/Mockaco_.log",
          "rollingInterval": "Day",
          "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {RequestId} {Message:lj}{NewLine}{Exception}"
        }
      }
    ]
  }
}

================================================
FILE: src/Mockaco/Settings/appsettings.json
================================================
{
  "Mockaco": {
    "DefaultHttpStatusCode": "OK",
    "ErrorHttpStatusCode": "NotImplemented",
    "DefaultHttpContentType": "application/json",
    "References": [],
    "VerificationIgnoredHeaders": [
        "Accept",
        "Connection",
        "Host",
        "User-Agent",
        "Accept-Encoding",
        "Postman-Token",
        "Content-Type",
        "Content-Length"
    ],
    "Imports": [],
    "MatchedRoutesCacheDuration": 60,
    "MockacoEndpoint": "_mockaco",
    "VerificationEndpointName": "verification",
    "Chaos": {
      "Enabled": false,
      "ChaosRate": 20,
      "MinimumLatencyTime": 500,
      "MaximumLatencyTime": 3000,
      "TimeBeforeTimeout": 10000
    }
  },
  "AllowedHosts": "*",
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Information",
        "System": "Information"
      }
    },
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Literate, Serilog.Sinks.Console",
          "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {RequestId} {Message:lj}{NewLine}{Exception}"
        }
      }
    ]
  }
}

================================================
FILE: src/Mockaco/Startup.Banner.cs
================================================
namespace Mockaco
{
    public partial class Startup
    {
        private const string _logo =
        "                                            .x000000000000000000000d.          \n" +
        "                                          .kMW0OkdooooooooooooooookNWd.        \n" +
        "                          ...           .kMNOdoc;;;;;;;;;;;;;;;;;;;:xNWx.      \n" +
        "                        lNMWM0'        kMNOdoc;;;;;;;;;;;;;;;;;;;;;;;:xNWl     \n" +
        "                       .MMo;OMx    :xxkWM0ddlcOKKKKKKKKKKKKKKKKKKKOc;;;kMNxxx: \n" +
        "                       .MMc;kMx   XMOloWM0ddKWNdllcccccccccccccccdNWx;;kMXoo0MO\n" +
        "                       .MMc;kMx  .WMc..XM0ddNMd......   .   ......dM0;;kMO..lMK\n" +
        "                       oMWc;kMx  .WMc..XM0ddNMd......   .   ......dM0;;kMO..lMK\n" +
        "      cOOOOOOOOOOOOOOONWOc;oXMo  .WMl..XM0ddXMK:,,'..............:KMO;;kMO..oMK\n" +
        "    lNMKOOxddddddddddddc;dXMO'    lXWNNMM0ddodXWWWMMx.......0MMWWWXo;;;kMWNNWX;\n" +
        "  lNWKxdkOkkkkkkkkkkkkkOXWk'        ..'NM0ddl;;:::0Mk.......0MO:::;;;;;kM0...  \n" +
        " NMXxdkXM0ddddddddddddddo.             XM0ddl;;;;;OMk.......0MO;;;;;;;;kMO     \n" +
        " WMOdOMN,        .,,,,,,,,,,,,,,,,,,   OMNkdo:;;;;dWWkoolllkWNd;;;;;;:dXMd     \n" +
        " WMOdOMK       ;0MNXXXXXXXXXXXXXXXXX:'''oXMXkdo:;;;:kKKKKKKKx:;;;;;:dXMO,      \n" +
        " WMOdOMK    .lXW0l;;;;;;;;;;;;;;;;;;;;;;;;oXMNOkxllllllllllllllllldXMk.        \n" +
        " WMOdOMK  .dWNOc;;;;;;;;;;;;;;;;;;;;;;;;;;;;oK000000000000000000000k.          \n" +
        " WMOdOMK .WMk:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;.                \n" +
        " WMOdkWWdoMN:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;lOl               \n" +
        " kWW0xdONMM0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;xM0               \n" +
        "  .dWWKxdkXx;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;xM0               \n" +
        "    .dNWKxdl:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;xM0               \n" +
        "       oNWKdol:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;lKMk               \n" +
        "        oMXddd:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cOMWl                \n" +
        "        OMKddo;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:kWW0xc                \n" +
        "        NMOddl;;;;;loooooooooooooooooooooooo:;;;;;;;;loxNMKxdloXK              \n" +
        "       'MMkddc;;;;oWWKNNNNXXXXXXK000000000WMd;;;;;;;;KMWXxo::;;0MO             \n" +
        "       cMWddd:;;;lWMc.odddc;;;;;.         kMk;;;;;;;cWMkddo:;;;:KMx            \n" +
        "       dMXddo;;;:KMx  :dddl;;;;x0c        lMK;;;;;;;dMX:dddo:;;;cNMl           \n" +
        "       0M0ddo;;;OMO  cNXddd:;;;OMk        ;MN:;;;;;;OMk ;dddo:;;;oWW,          \n" +
        "       NMOddl;;xMX.  'MWxddl;;;OMk        .MMl;;;;;;XMl .xOddo:;;;oWN.         \n" +
        "      ,MWxddc;lWW'    OM0ddo;;;OMk         NMd;;;;;lMM, .XMKddo;;;;kM0         \n" +
        "      lMNkkkooNMl     cMNkkkollKMO         0MOlllllkMW.  .KM0kkxllloXMk.       \n" +
        "      kMWNNNNNNWNl    .NMWNNNNNNNWNo.      xMWNNNNNNNWNo. .KMMNNNNNNNNNMK;     \n" +
        "      XMl......'dNNc   kMx.......'dNNc     oMK........dNNc .NMd........;OMX'   \n" +
        "     'MM0OOkkkkkkXM0   :MNOOOkkkkkkKM0     :MWOOOkkkkkkKMO  .XWOOOkkkkkkkWMl   \n" +
        "     :WWWWWWWWWWWWWO   .WWWWWWWWWWWWWO     ,WWWWWWWWWWWWWk   ;WWWWWWWWWWWWWc   \n";
    }
}


================================================
FILE: src/Mockaco/Startup.cs
================================================
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Reflection;
using System;
using System.Linq;

namespace Mockaco
{
    public partial class Startup
    {
        private readonly IConfiguration _configuration;

        public Startup(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services
                .AddCors()
                .AddMockaco(_configuration.GetSection("Mockaco"));
        }

        public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
        {
            var assemblyName = Assembly.GetExecutingAssembly().GetName().Name;
            var version = GitVersionInformation.InformationalVersion;
            var isNoLogoPassed = Environment.GetCommandLineArgs().Contains("--no-logo");

            var logMessage = "{assemblyName} v{assemblyVersion} [github.com/natenho/Mockaco]";

            if (!isNoLogoPassed)
                logMessage += "\n\n{logo}";

            logger.LogInformation(logMessage, assemblyName, version, _logo);

            app
                .UseCors()
                .UseMockaco();
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyBehavior.cs
================================================
using System.Net;
using System.Text;
using Microsoft.AspNetCore.Http;

namespace Mockaco.Chaos.Strategies;

internal class ChaosStrategyBehavior : IChaosStrategy
{
    public Task Response(HttpResponse httpResponse)
    {
        httpResponse.StatusCode = (int)HttpStatusCode.ServiceUnavailable;

        var bodyBytes = Encoding.UTF8.GetBytes($"Error {httpResponse.StatusCode}: {HttpStatusCode.ServiceUnavailable}");

        return httpResponse.Body.WriteAsync(bodyBytes, 0, bodyBytes.Length, default);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyException.cs
================================================
using System.Net;
using System.Text;
using Microsoft.AspNetCore.Http;

namespace Mockaco.Chaos.Strategies;

internal class ChaosStrategyException : IChaosStrategy
{
    public Task Response(HttpResponse httpResponse)
    {
        httpResponse.StatusCode = (int)HttpStatusCode.InternalServerError;

        var bodyBytes = Encoding.UTF8.GetBytes($"Error {httpResponse.StatusCode}: {HttpStatusCode.InternalServerError}");

        return httpResponse.Body.WriteAsync(bodyBytes, 0, bodyBytes.Length);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyLatency.cs
================================================
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Mockaco.Chaos.Strategies;

internal class ChaosStrategyLatency : IChaosStrategy
{
    private readonly ILogger<ChaosStrategyLatency> _logger;
    private readonly IOptions<ChaosOptions> _options;

    public ChaosStrategyLatency(ILogger<ChaosStrategyLatency> logger, IOptions<ChaosOptions> options)
    {
        _logger = logger;
        _options = options;
    }
    public Task Response(HttpResponse httpResponse)
    {
        var responseDelay = new Random().Next(_options.Value.MinimumLatencyTime, _options.Value.MaximumLatencyTime);
        _logger.LogInformation($"Chaos Latency (ms): {responseDelay}");
        return Task.Delay(responseDelay);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyResult.cs
================================================
using System.Net;
using System.Text;
using Microsoft.AspNetCore.Http;

namespace Mockaco.Chaos.Strategies;

internal class ChaosStrategyResult : IChaosStrategy
{
    public Task Response(HttpResponse httpResponse)
    {
        httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;

        var bodyBytes = Encoding.UTF8.GetBytes($"Error {httpResponse.StatusCode}: {HttpStatusCode.BadRequest}");

        return httpResponse.Body.WriteAsync(bodyBytes, 0, bodyBytes.Length);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyTimeout.cs
================================================
using System.Net;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;

namespace Mockaco.Chaos.Strategies;

internal class ChaosStrategyTimeout : IChaosStrategy
{
    private readonly IOptions<ChaosOptions> _options;

    public ChaosStrategyTimeout(IOptions<ChaosOptions> options)
    {
        _options = options;
    }
    
    public async Task Response(HttpResponse httpResponse)
    {
        await Task.Delay(_options.Value.TimeBeforeTimeout);

        httpResponse.StatusCode = (int)HttpStatusCode.RequestTimeout;

        var bodyBytes = Encoding.UTF8.GetBytes($"Error {httpResponse.StatusCode}: {HttpStatusCode.RequestTimeout}");

        await httpResponse.Body.WriteAsync(bodyBytes, 0, bodyBytes.Length, default);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Chaos/Strategies/IChaosStrategy.cs
================================================
using Microsoft.AspNetCore.Http;

namespace Mockaco.Chaos.Strategies;

internal interface IChaosStrategy
{
    Task Response(HttpResponse httpResponse);
}

================================================
FILE: src/Mockaco.AspNetCore/Common/HttpContentTypes.cs
================================================
namespace Mockaco
{
    internal static class HttpContentTypes
    {
        public const string ApplicationOctetStream = "application/octet-stream";
        public const string ApplicationJson = "application/json";
        public const string ApplicationXml = "application/xml";
        public const string TextXml = "text/xml";
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Common/HttpHeaders.cs
================================================
namespace Mockaco
{
    internal static class HttpHeaders
    {
        public const string ContentType = "Content-Type";
        public const string AcceptLanguage = "Accept-Language";
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Common/InvalidMockException.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace Mockaco.Common
{
    internal class InvalidMockException : Exception
    {
        public InvalidMockException() : base() { }

        public InvalidMockException(string message) : base(message)
        {
        }

        public InvalidMockException(string message, Exception innerException) : base(message, innerException)
        {
        }

        protected InvalidMockException(SerializationInfo info, StreamingContext context) : base(info, context)
        {
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Common/RouteMatcher.cs
================================================
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Template;

namespace Mockaco
{
    internal class RouteMatcher
    {
        public RouteValueDictionary Match(string routeTemplate, string requestPath)
        {
            if(string.IsNullOrWhiteSpace(routeTemplate))
            {
                return null;
            }

            var template = TemplateParser.Parse(routeTemplate);

            var matcher = new TemplateMatcher(template, GetDefaults(template));

            var values = new RouteValueDictionary();

            return matcher.TryMatch(requestPath, values) ? values : null;
        }

        public bool IsMatch(string routeTemplate, string requestPath)
        {
            return Match(routeTemplate, requestPath) != null;
        }

        private RouteValueDictionary GetDefaults(RouteTemplate parsedTemplate)
        {
            var result = new RouteValueDictionary();

            foreach (var parameter in parsedTemplate.Parameters)
            {
                if (parameter.DefaultValue != null)
                {
                    result.Add(parameter.Name, parameter.DefaultValue);
                }
            }

            return result;
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Common/SimpleExceptionConverter.cs
================================================
namespace Mockaco.Common
{
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using System;

    internal class SimpleExceptionConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(Exception).IsAssignableFrom(objectType);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException("Deserializing exceptions is not supported.");
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var exception = value as Exception;
            if (exception == null)
            {
                serializer.Serialize(writer, null);
                return;
            }

            var obj = new JObject
            {
                ["Type"] = exception.GetType().Name,
                ["Message"] = exception.Message,

            };

            if (exception.Data.Count > 0)
            {
                obj["Data"] = JToken.FromObject(exception.Data, serializer);
            }

            if (exception.InnerException != null)
            {
                obj["InnerException"] = JToken.FromObject(exception.InnerException, serializer);
            }

            obj.WriteTo(writer);
        }
    }

}


================================================
FILE: src/Mockaco.AspNetCore/Common/StringDictionary.cs
================================================
using System.Collections.Generic;

namespace Mockaco
{
    public class StringDictionary : Dictionary<string, string>, IReadOnlyDictionary<string, string>
    {
        public new string this[string key]
        {
            get
            {
                if (TryGetValue(key, out string value))
                {
                    return value;
                }

                return string.Empty;
            }
            set
            {
                base[key] = value;
            }
        }

        public new void Add(string key, string value)
        {
            Replace(key, value);
        }

        public void Replace(string key, string value)
        {
            if (ContainsKey(key))
            {
                Remove(key);
            }

            base.Add(key, value);
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/DependencyInjection/MockacoApplicationBuilder.cs
================================================
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Mockaco;
using Mockaco.Verifyer;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;

namespace Microsoft.AspNetCore.Builder
{
    public static class MockacoApplicationBuilder
    {
        public static IApplicationBuilder UseMockaco(this IApplicationBuilder app, Action<IApplicationBuilder> configure)
        {
            app.UseRouting();

            var options = app.ApplicationServices.GetRequiredService<IOptions<MockacoOptions>>().Value;

            var optionsChaos = app.ApplicationServices.GetRequiredService<IOptions<ChaosOptions>>().Value;

            app.UseEndpoints(endpoints =>
            {
                endpoints.Map($"/{options.VerificationEndpointPrefix ?? options.MockacoEndpoint}/{options.VerificationEndpointName}", VerifyerExtensions.Verify);

                endpoints.MapHealthChecks($"/{options.MockacoEndpoint}/ready", new HealthCheckOptions
                {
                    Predicate = healthCheck => healthCheck.Tags.Contains("ready")
                });

                endpoints.MapHealthChecks($"/{options.MockacoEndpoint}/health", new HealthCheckOptions
                {
                    Predicate = _ => false
                });
            });

            app.UseMiddleware<ErrorHandlingMiddleware>();
            configure(app);
            app
                .UseMiddleware<RequestMatchingMiddleware>()
                .UseMiddleware<ResponseDelayMiddleware>()
                .UseMiddleware<ChaosMiddleware>()
                .UseMiddleware<ResponseMockingMiddleware>()
                .UseMiddleware<CallbackMiddleware>();

            return app;
        }

        public static IApplicationBuilder UseMockaco(this IApplicationBuilder app) =>
            app.UseMockaco(_ => { });
    }
}


================================================
FILE: src/Mockaco.AspNetCore/DependencyInjection/MockacoServiceCollection.cs
================================================
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Options;
using Mockaco;
using Mockaco.Chaos.Strategies;
using Mockaco.HealthChecks;
using Mockaco.Settings;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class MockacoServiceCollection
    {
        public static IServiceCollection AddMockaco(this IServiceCollection services) =>
            services.AddMockaco(_ => { });

        public static IServiceCollection AddMockaco(this IServiceCollection services, Action<MockacoOptions> config) =>
            services
                .AddOptions<MockacoOptions>().Configure(config).Services
                .AddOptions<ChaosOptions>().Configure<IOptions<MockacoOptions>>((options, parent) => options = parent.Value.Chaos).Services
                .AddOptions<TemplateFileProviderOptions>()
                    .Configure<IOptions<MockacoOptions>>((options, parent) => options = parent.Value.TemplateFileProvider)
                    .Services
                .AddCommonServices();


        public static IServiceCollection AddMockaco(this IServiceCollection services, IConfiguration config) =>
            services
                .AddConfiguration(config)
                .AddCommonServices();

        private static IServiceCollection AddConfiguration(this IServiceCollection services, IConfiguration config) =>
            services
                .AddOptions()
                .Configure<MockacoOptions>(config)
                .Configure<ChaosOptions>(config.GetSection("Chaos"))
                .Configure<TemplateFileProviderOptions>(config.GetSection("TemplateFileProvider"));

        private static IServiceCollection AddCommonServices(this IServiceCollection services)
        {
            services
                .AddMemoryCache()
                .AddHttpClient()
                .AddInternalServices()
                .AddChaosServices()
                .AddHostedService<MockProviderWarmUp>();

            services
                .AddSingleton<StartupHealthCheck>()
                .AddHealthChecks()
                    .AddCheck<StartupHealthCheck>("Startup", tags: new[] { "ready" });

            return services;
        }

        private static IServiceCollection AddInternalServices(this IServiceCollection services) =>
            services
                .AddSingleton<VerificationRouteValueTransformer>()
                .AddScoped<IMockacoContext, MockacoContext>()
                .AddScoped<IScriptContext, ScriptContext>()
                .AddTransient<IGlobalVariableStorage, ScriptContextGlobalVariableStorage>()

                .AddSingleton<IScriptRunnerFactory, ScriptRunnerFactory>()

                .AddSingleton<IFakerFactory, LocalizedFakerFactory>()
                .AddSingleton<IMockProvider, MockProvider>()
                .AddSingleton<ITemplateProvider, TemplateFileProvider>()

                .AddScoped<IRequestMatcher, RequestMethodMatcher>()
                .AddScoped<IRequestMatcher, RequestRouteMatcher>()
                .AddScoped<IRequestMatcher, RequestConditionMatcher>()

                .AddTransient<IRequestBodyFactory, RequestBodyFactory>()

                .AddTransient<IRequestBodyStrategy, JsonRequestBodyStrategy>()
                .AddTransient<IRequestBodyStrategy, XmlRequestBodyStrategy>()
                .AddTransient<IRequestBodyStrategy, FormRequestBodyStrategy>()

                .AddTransient<IResponseBodyFactory, ResponseBodyFactory>()

                .AddTransient<IResponseBodyStrategy, BinaryResponseBodyStrategy>()
                .AddTransient<IResponseBodyStrategy, JsonResponseBodyStrategy>()
                .AddTransient<IResponseBodyStrategy, XmlResponseBodyStrategy>()
                .AddTransient<IResponseBodyStrategy, DefaultResponseBodyStrategy>()

                .AddTransient<ITemplateTransformer, TemplateTransformer>()

                .AddTemplatesGenerating();

        private static IServiceCollection AddChaosServices(this IServiceCollection services) =>
            services
                .AddTransient<IChaosStrategy, ChaosStrategyBehavior>()
                .AddTransient<IChaosStrategy, ChaosStrategyException>()
                .AddTransient<IChaosStrategy, ChaosStrategyLatency>()
                .AddTransient<IChaosStrategy, ChaosStrategyResult>()
                .AddTransient<IChaosStrategy, ChaosStrategyTimeout>();
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Extensions/EnumerableExtensions.cs
================================================
using System.Threading.Tasks;

namespace System.Collections.Generic
{
    internal static class EnumerableExtensions
    {
        public static async Task<bool> AllAsync<TSource>(this IEnumerable<TSource> source, Func<TSource, Task<bool>> predicate)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            if (predicate == null)
                throw new ArgumentNullException(nameof(predicate));

            foreach (var item in source)
            {
                var result = await predicate(item);
                if (!result)
                    return false;
            }

            return true;
        }

        public static async Task<bool> AllAsync<TSource>(this IEnumerable<Task<TSource>> source, Func<TSource, bool> predicate)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            if (predicate == null)
                throw new ArgumentNullException(nameof(predicate));

            foreach (var item in source)
            {
                var awaitedItem = await item;
                if (!predicate(awaitedItem))
                    return false;
            }

            return true;
        }
        
        public static T Random<T>(this IEnumerable<T> enumerable) { 
            int index = new Random().Next(0, enumerable.Count());
            return enumerable.ElementAt(index);
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Extensions/HttpRequestExtensions.cs
================================================
/*
The MIT License (MIT)

Copyright (c) 2015 Microsoft

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.
*/

using Microsoft.Net.Http.Headers;
using Mockaco;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.AspNetCore.Http
{
    /// <summary>
    /// Set of extension methods for Microsoft.AspNetCore.Http.HttpRequest
    /// </summary>
    internal static class HttpRequestExtensions
    {
        private const string UnknownHostName = "UNKNOWN-HOST";

        /// <summary>
        /// Gets http request Uri from request object
        /// </summary>
        /// <param name="request">The <see cref="HttpRequest"/></param>
        /// <returns>A New Uri object representing request Uri</returns>
        public static Uri GetUri(this HttpRequest request)
        {
            if (null == request)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (string.IsNullOrWhiteSpace(request.Scheme))
            {
                throw new ArgumentException("Http request Scheme is not specified");
            }

            string hostName = request.Host.HasValue ? request.Host.ToString() : UnknownHostName;

            var builder = new StringBuilder();

            builder.Append(request.Scheme)
                .Append("://")
                .Append(hostName);

            if (request.Path.HasValue)
            {
                builder.Append(request.Path.Value);
            }

            if (request.QueryString.HasValue)
            {
                builder.Append(request.QueryString);
            }

            return new Uri(builder.ToString());
        }

        public static Routing.RouteValueDictionary GetRouteData(this HttpRequest request, Mock mock)
        {
            var routeMatcher = new RouteMatcher();

            return routeMatcher.Match(mock.Route, request.Path);
        }

        public static bool HasXmlContentType(this HttpRequest request)
        {
            MediaTypeHeaderValue.TryParse(request.ContentType, out var parsedValue);

            return parsedValue?.MediaType.Equals(HttpContentTypes.ApplicationXml, StringComparison.OrdinalIgnoreCase) == true
                || parsedValue?.MediaType.Equals(HttpContentTypes.TextXml, StringComparison.OrdinalIgnoreCase) == true;
        }

        public static async Task<string> ReadBodyStream(this HttpRequest httpRequest)
        {
            httpRequest.EnableBuffering();

            var encoding = GetEncodingFromContentType(httpRequest.ContentType) ?? Encoding.UTF8;
            var reader = new StreamReader(httpRequest.Body, encoding); 

            var body = await reader.ReadToEndAsync();

            if (httpRequest.Body.CanSeek)
            {
                httpRequest.Body.Seek(0, SeekOrigin.Begin);
            }

            return body;
        }

        public static IEnumerable<string> GetAcceptLanguageValues(this HttpRequest httpRequest)
        {
            var acceptLanguages = httpRequest.GetTypedHeaders().AcceptLanguage;

            if(acceptLanguages == default)
            {
                return Enumerable.Empty<string>();
            }

            return acceptLanguages?.Select(l => l.Value.ToString());
        }

        private static Encoding GetEncodingFromContentType(string contentType)
        {
            // although the value is well parsed, the encoding is null when it is not informed
            if (MediaTypeHeaderValue.TryParse(contentType, out var parsedValue))
                return parsedValue.Encoding;

            return null;
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Extensions/ObjectExtensions.cs
================================================
using Mockaco.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using System.Linq;

namespace System
{
    internal static class ObjectExtensions
    {
        private static readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings
        {
            Formatting = Formatting.Indented,
            Converters = new JsonConverter[] {
                new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy()},
                new SimpleExceptionConverter()
            },
            NullValueHandling = NullValueHandling.Ignore
        };

        public static string ToJson<T>(this T param)
            where T : class
        {
            if (param == null)
            {
                return string.Empty;
            }

            try
            {
                return JsonConvert.SerializeObject(param, _jsonSerializerSettings);
            }
            catch
            {
                return string.Empty;
            }
        }

        public static bool IsAnyOf<T>(this T item, params T[] possibleItems)
        {
            return possibleItems.Contains(item);
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Extensions/StringDictionaryExtensions.cs
================================================
using Mockaco;

namespace System.Collections.Generic
{
    internal static class StringDictionaryExtensions
    {
        public static StringDictionary ToStringDictionary<TSource>(
            this IEnumerable<TSource> source,
            Func<TSource, string> keySelector,
            Func<TSource, string> elementSelector)
        {
            var dictionary = new StringDictionary();

            if (source == null)
            {
                return dictionary;
            }

            foreach (var item in source)
            {
                dictionary.Add(keySelector(item), elementSelector(item));
            }

            return dictionary;
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Extensions/StringExtensions.cs
================================================
using System.Text;

namespace System
{
    internal static class StringExtensions
    {
        public static string ToMD5Hash(this string input)
        {
            using (Security.Cryptography.MD5 md5 = Security.Cryptography.MD5.Create())
            {
                var inputBytes = Encoding.UTF8.GetBytes(input);
                var hashBytes = md5.ComputeHash(inputBytes);

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < hashBytes.Length; i++)
                {
                    sb.Append(hashBytes[i].ToString("X2"));
                }
                return sb.ToString();
            }
        }
        
        public static bool IsRemoteAbsolutePath(this string input)
        {
            if (Uri.TryCreate(input, UriKind.Absolute, out var uri))
            {
                return !uri.IsFile;
            }

            return false;
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/HealthChecks/StartupHealthCheck.cs
================================================
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace Mockaco.HealthChecks
{
    public class StartupHealthCheck : IHealthCheck
    {
        private volatile bool _isReady;

        public bool StartupCompleted
        {
            get => _isReady;
            set => _isReady = value;
        }

        public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            if (StartupCompleted)
            {
                return Task.FromResult(HealthCheckResult.Healthy("The startup has completed."));
            }

            return Task.FromResult(HealthCheckResult.Unhealthy("That startup is still running."));
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/IMockProvider.cs
================================================
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Mockaco
{
    internal interface IMockProvider
    {
        List<Mock> GetMocks();

        IEnumerable<(string TemplateName, string ErrorMessage)> GetErrors();

        Task WarmUp();
    }
}

================================================
FILE: src/Mockaco.AspNetCore/IMockacoContext.cs
================================================
using System.Collections.Generic;

namespace Mockaco
{
    internal interface IMockacoContext
    {
        IScriptContext ScriptContext { get; }

        Template TransformedTemplate { get; set; }

        Mock Mock { get; set; }

        List<Error> Errors { get; set; }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/InternalsVisibleTo.cs
================================================
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Mockaco.AspNetCore.Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]


================================================
FILE: src/Mockaco.AspNetCore/Middlewares/CallbackMiddleware.cs
================================================
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace Mockaco
{
    internal class CallbackMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<CallbackMiddleware> _logger;

        public CallbackMiddleware(RequestDelegate next, ILogger<CallbackMiddleware> logger)
        {
            _next = next;
            _logger = logger;
        }

        public Task Invoke(
            HttpContext httpContext,
            IMockacoContext mockacoContext,
            IScriptContext scriptContext,
            ITemplateTransformer templateTransformer,
            IOptionsSnapshot<MockacoOptions> options)
        {
            if (mockacoContext.TransformedTemplate?.Callbacks?.Any() != true)
            {
                return Task.CompletedTask;
            }

            httpContext.Response.OnCompleted(
                () =>
                {
                    //TODO Refactor to avoid method with too many parameters (maybe a CallbackRunnerFactory?)
                    var fireAndForgetTask = PerformCallbacks(httpContext, mockacoContext, scriptContext, templateTransformer, options.Value);
                    return Task.CompletedTask;
                });

            return Task.CompletedTask;
        }
        
        private async Task PerformCallbacks(
            HttpContext httpContext,
            IMockacoContext mockacoContext,
            IScriptContext scriptContext,
            ITemplateTransformer templateTransformer,
            MockacoOptions options)
        {
            try
            {
                var stopwatch = Stopwatch.StartNew();
                                
                var template = await templateTransformer.Transform(mockacoContext.Mock.RawTemplate, scriptContext);

                var callbackTasks = new List<Task>();

                foreach (var callbackTemplate in template.Callbacks)
                {
                    callbackTasks.Add(PerformCallback(httpContext, callbackTemplate, options, stopwatch.ElapsedMilliseconds));
                }

                await Task.WhenAll(callbackTasks);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error preparing callback(s)");
            }
        }

        private async Task PerformCallback(HttpContext httpContext, CallbackTemplate callbackTemplate, MockacoOptions options, long elapsedMilliseconds)
        {
            try
            {
                var request = PrepareHttpRequest(callbackTemplate, options);

                var httpClient = PrepareHttpClient(httpContext, callbackTemplate);

                await DelayRequest(callbackTemplate, elapsedMilliseconds);

                var stopwatch = Stopwatch.StartNew();

                _logger.LogDebug("Callback started");

                await PerformRequest(request, httpClient);

                _logger.LogDebug("Callback finished in {0} ms", stopwatch.ElapsedMilliseconds);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Callback error");
            }
        }

        private static HttpRequestMessage PrepareHttpRequest(CallbackTemplate callbackTemplate, MockacoOptions options)
        {
            var request = new HttpRequestMessage(new HttpMethod(callbackTemplate.Method), callbackTemplate.Url);

            var formatting = callbackTemplate.Indented.GetValueOrDefault(true) ? Formatting.Indented : default;

            if (callbackTemplate.Body != null)
            {
                request.Content = callbackTemplate.Headers?.ContainsKey(HttpHeaders.ContentType) == true
                    ? new StringContent(callbackTemplate.Body.ToString(), Encoding.UTF8, callbackTemplate.Headers[HttpHeaders.ContentType])
                    : new StringContent(callbackTemplate.Body.ToString(formatting));
            }

            PrepareHeaders(callbackTemplate, request, options);

            return request;
        }

        private static void PrepareHeaders(CallbackTemplate callBackTemplate, HttpRequestMessage httpRequest, MockacoOptions options)
        {
            if (callBackTemplate.Headers != null)
            {
                foreach (var header in callBackTemplate.Headers.Where(h => h.Key != HttpHeaders.ContentType))
                {
                    if (httpRequest.Headers.Contains(header.Key))
                    {
                        httpRequest.Headers.Remove(header.Key);
                    }

                    httpRequest.Headers.Add(header.Key, header.Value);
                }
            }

            if (!httpRequest.Headers.Accept.Any())
            {
                httpRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(options.DefaultHttpContentType));
            }
        }

        private static HttpClient PrepareHttpClient(HttpContext httpContext, CallbackTemplate callbackTemplate)
        {
            var factory = httpContext.RequestServices.GetService<IHttpClientFactory>();
            var httpClient = factory.CreateClient();

            httpClient.Timeout = TimeSpan.FromMilliseconds(callbackTemplate.Timeout.GetValueOrDefault());

            return httpClient;
        }

        private async Task DelayRequest(CallbackTemplate callbackTemplate, long elapsedMilliseconds)
        {
            var remainingDelay = TimeSpan.FromMilliseconds(callbackTemplate.Delay.GetValueOrDefault() - elapsedMilliseconds);
            if (elapsedMilliseconds < remainingDelay.TotalMilliseconds)
            {
                _logger.LogDebug("Callback delay: {0} milliseconds", remainingDelay.TotalMilliseconds);
                await Task.Delay(remainingDelay);
            }
        }

        private async Task PerformRequest(HttpRequestMessage request, HttpClient httpClient)
        {
            try
            {
                var response = await httpClient.SendAsync(request);

                _logger.LogDebug("Callback response\n\n{0}\n", response);
                _logger.LogDebug("Callback response content\n\n{0}\n", await response.Content.ReadAsStringAsync());
            }
            catch (OperationCanceledException)
            {
                _logger.LogError("Callback request timeout");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Callback error");
            }
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Middlewares/ChaosMiddleware.cs
================================================
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Mockaco.Chaos.Strategies;

namespace Mockaco;

internal class ChaosMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IEnumerable<IChaosStrategy> _strategies;
    private readonly ILogger<ChaosMiddleware> _logger;
    private readonly IOptions<ChaosOptions> _options;

    private List<int> ErrorList { get; set; }
    private int Counter { get; set; }

    public ChaosMiddleware(
        RequestDelegate next,
        IEnumerable<IChaosStrategy> strategies,
        ILogger<ChaosMiddleware> logger,
        IOptions<ChaosOptions> options)
    {
        _next = next;
        _strategies = strategies;
        _logger = logger;
        _options = options;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        if (!_options.Value.Enabled)
        {
            await _next(httpContext);
            return;
        }

        Counter++;
        if (Counter > 100)
            Counter = 1;

        if (Counter == 1)
            ErrorList = GenerateErrorList(_options.Value.ChaosRate);

        if (ErrorList.Contains(Counter))
        {
            var selected = _strategies.Random();
            _logger.LogInformation($"Chaos: {selected?.ToString()}");
            if (selected != null) await selected.Response(httpContext.Response);
        }

        if (httpContext.Response.StatusCode != (int)HttpStatusCode.OK)
            return;

        await _next(httpContext);
    }

    private List<int> GenerateErrorList(int rate)
    {
        var list = new List<int>();
        while (list.Count < rate)
        {
            var item = new Random().Next(1, 100);
            if (!list.Contains(item))
            {
                list.Add(item);
            }
        }

        return list.OrderBy(x => x).ToList();
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Middlewares/ErrorHandlingMiddleware.cs
================================================
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace Mockaco
{
    internal class ErrorHandlingMiddleware
    {
        private readonly RequestDelegate _next;

        public ErrorHandlingMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(
            HttpContext httpContext,
            IMockacoContext mockacoContext,
            IOptionsSnapshot<MockacoOptions> statusCodeOptions,
            IMockProvider mockProvider,
            ILogger<ErrorHandlingMiddleware> logger)
        {
            try
            {
                await _next(httpContext);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Error generating mocked response");

                mockacoContext.Errors.Add(new Error("Error generating mocked response", ex));
            }
            finally
            {
                if (mockacoContext.Errors.Any() && !httpContext.Response.HasStarted)
                {
                    httpContext.Response.StatusCode = (int)statusCodeOptions.Value.ErrorHttpStatusCode;
                    httpContext.Response.ContentType = HttpContentTypes.ApplicationJson;

                    IncludeMockProviderErrors(mockacoContext, mockProvider);

                    await httpContext.Response.WriteAsync(mockacoContext.Errors.ToJson());
                }
            }
        }

        private static void IncludeMockProviderErrors(IMockacoContext mockacoContext, IMockProvider mockProvider)
        {
            mockacoContext.Errors
                .AddRange(mockProvider.GetErrors()
                    .Select(_ => new Error($"{_.TemplateName} - {_.ErrorMessage}")));
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Middlewares/RequestMatchingMiddleware.cs
================================================
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;

namespace Mockaco
{
    internal class RequestMatchingMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<RequestMatchingMiddleware> _logger;

        public RequestMatchingMiddleware(RequestDelegate next, ILogger<RequestMatchingMiddleware> logger)
        {
            _next = next;
            _logger = logger;
        }

        public async Task Invoke(
            HttpContext httpContext,
            IMockacoContext mockacoContext,
            IScriptContext scriptContext,
            IMockProvider mockProvider,
            ITemplateTransformer templateTransformer,
            IEnumerable<IRequestMatcher> requestMatchers,
            IMemoryCache cache,
            IOptions<MockacoOptions> options
            )
        {
            await LogHttpContext(httpContext);

            await AttachRequestToScriptContext(httpContext, mockacoContext, scriptContext);

            if (mockacoContext.Errors.Any())
            {
                return;
            }

            foreach (var mock in mockProvider.GetMocks())
            {
                if (await requestMatchers.AllAsync(_ => _.IsMatch(httpContext.Request, mock)))
                {
                    cache.Set($"{nameof(RequestMatchingMiddleware)} {httpContext.Request.Path.Value}",new
                    {
                        Route = httpContext.Request.Path.Value,
                        Timestamp = $"{DateTime.Now.ToString("t")}",
                        Headers = LoadHeaders(httpContext, options.Value.VerificationIgnoredHeaders),
                        Body = await httpContext.Request.ReadBodyStream()
                    }, DateTime.Now.AddMinutes(options.Value.MatchedRoutesCacheDuration));

                    _logger.LogInformation("Incoming request matched {mock}", mock);

                    await scriptContext.AttachRouteParameters(httpContext.Request, mock);

                    var template = await templateTransformer.TransformAndSetVariables(mock.RawTemplate, scriptContext);

                    mockacoContext.Mock = mock;
                    mockacoContext.TransformedTemplate = template;

                    await _next(httpContext);

                    return;
                }
                else
                {
                    _logger.LogDebug("Incoming request didn't match {mock}", mock);
                }
            }

            _logger.LogInformation("Incoming request didn't match any mock");

            mockacoContext.Errors.Add(new Error("Incoming request didn't match any mock"));
        }

        //TODO Remove redundant code
        private async Task AttachRequestToScriptContext(HttpContext httpContext, IMockacoContext mockacoContext, IScriptContext scriptContext)
        {
            try
            {
                await scriptContext.AttachRequest(httpContext.Request);
            }
            catch (Exception ex)
            {
                mockacoContext.Errors.Add(new Error("An error occurred while reading request", ex));

                _logger.LogWarning(ex, "An error occurred while reading request");

                return;
            }
        }

        private async Task LogHttpContext(HttpContext httpContext)
        {
            _logger.LogInformation("Incoming request from {remoteIp}", httpContext.Connection.RemoteIpAddress);

            _logger.LogDebug("Headers: {headers}", httpContext.Request.Headers.ToJson());

            var body = await httpContext.Request.ReadBodyStream();

            if (string.IsNullOrEmpty(body))
            {
                _logger.LogDebug("Body is not present");
            }
            else
            {
                _logger.LogDebug("Body: {body}", body);
            }
        }

        private static IEnumerable<object> LoadHeaders(HttpContext httpContext, IEnumerable<string> verificationIgnoredHeaders)
        {            
            return from header in httpContext.Request.Headers.ToList()
                   where !verificationIgnoredHeaders.Any(opt => opt == header.Key)
                   select new { header.Key, Value = header.Value[0] };
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Middlewares/ResponseDelayMiddleware.cs
================================================
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Threading.Tasks;

namespace Mockaco
{
    internal class ResponseDelayMiddleware
    {
        private readonly RequestDelegate _next;

        public ResponseDelayMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext httpContext, IMockacoContext mockacoContext, ILogger<ResponseDelayMiddleware> logger)
        {
            var transformedTemplate = mockacoContext.TransformedTemplate;
            if (transformedTemplate == default)
            {
                return;
            }

            int responseDelay = transformedTemplate.Response?.Delay.GetValueOrDefault() ?? 0;
            if (responseDelay > 0)
            {
                logger.LogDebug("Response delay: {responseDelay} milliseconds", responseDelay);

                await Task.Delay(responseDelay);
            }

            await _next(httpContext);
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Middlewares/ResponseMockingMiddleware.cs
================================================
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System.Net;
using System.Threading.Tasks;

namespace Mockaco
{
    internal class ResponseMockingMiddleware
    {
        private readonly RequestDelegate _next;

        public ResponseMockingMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(
            HttpContext httpContext,
            IMockacoContext mockacoContext,
            IScriptContext scriptContext,
            IResponseBodyFactory responseBodyFactory,
            IOptionsSnapshot<MockacoOptions> options)
        {
            await PrepareResponse(httpContext.Response, mockacoContext.TransformedTemplate, responseBodyFactory, options.Value);

            await scriptContext.AttachResponse(httpContext.Response, mockacoContext.TransformedTemplate.Response);

            await _next(httpContext);
        }

        private async Task PrepareResponse(
            HttpResponse httpResponse,
            Template transformedTemplate,
            IResponseBodyFactory responseBodyFactory,
            MockacoOptions options)
        {
            httpResponse.StatusCode = GetResponseStatusFromTemplate(transformedTemplate.Response, options);

            AddHeadersFromTemplate(httpResponse, transformedTemplate.Response, options);

            var bodyBytes = await responseBodyFactory.GetResponseBodyBytesFromTemplate(transformedTemplate.Response);

            if (bodyBytes == default)
            {
                return;
            }

            await httpResponse.Body.WriteAsync(bodyBytes, 0, bodyBytes.Length, default);
        }

        private int GetResponseStatusFromTemplate(ResponseTemplate responseTemplate, MockacoOptions options)
        {
            return responseTemplate?.Status == default(HttpStatusCode)
                            ? (int)options.DefaultHttpStatusCode
                            : (int)responseTemplate.Status;
        }

        private void AddHeadersFromTemplate(HttpResponse response, ResponseTemplate responseTemplate, MockacoOptions options)
        {
            if (responseTemplate?.Headers != null)
            {
                foreach (var header in responseTemplate.Headers)
                {
                    response.Headers.Add(header.Key, header.Value);
                }
            }

            if (string.IsNullOrEmpty(response.ContentType))
            {
                response.ContentType = options.DefaultHttpContentType;
            }
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/MockProvider.cs
================================================
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using Mockaco.HealthChecks;
using Mono.TextTemplating;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Mockaco
{
    internal class MockProvider : IMockProvider
    {
        private List<Mock> _cache;
        private readonly List<(string TemplateName, string ErrorMessage)> _errors = new List<(string TemplateName, string Error)>();        
        private readonly IFakerFactory _fakerFactory;
        private readonly IRequestBodyFactory _requestBodyFactory;
        private readonly ITemplateProvider _templateProvider;
        private readonly ITemplateTransformer _templateTransformer;
        private readonly IGlobalVariableStorage _globalVariableStorage;
        private readonly StartupHealthCheck _healthCheck;
        private readonly ILogger<MockProvider> _logger;

        public MockProvider
            (IFakerFactory fakerFactory, 
            IRequestBodyFactory requestBodyFactory, 
            ITemplateProvider templateProvider, 
            ITemplateTransformer templateTransformer, 
            IGlobalVariableStorage globalVariableStorage,
            StartupHealthCheck healthCheck,
            ILogger<MockProvider> logger)
        {
            _cache = new List<Mock>();
            _fakerFactory = fakerFactory;
            _requestBodyFactory = requestBodyFactory;
            _templateProvider = templateProvider;
            _templateProvider.OnChange += TemplateProviderChange;

            _templateTransformer = templateTransformer;
            _globalVariableStorage = globalVariableStorage;
            _healthCheck = healthCheck;
            _logger = logger;
        }

        private async void TemplateProviderChange(object sender, EventArgs e)
        {
            await WarmUp();
        }

        //TODO: Fix potential thread-unsafe method
        public List<Mock> GetMocks()
        {
            return _cache;
        }

        public IEnumerable<(string TemplateName, string ErrorMessage)> GetErrors()
        {
            return _errors;
        }

        public async Task WarmUp()
        {
            var stopwatch = Stopwatch.StartNew();

            var warmUpScriptContext = new ScriptContext(_fakerFactory, _requestBodyFactory, _globalVariableStorage);

            const int defaultCapacity = 16;
            var mocks = new List<Mock>(_cache.Count > 0 ? _cache.Count : defaultCapacity);

            _errors.Clear();

            foreach (var rawTemplate in _templateProvider.GetTemplates())
            {
                try
                {
                    var existentCachedRoute = _cache.FirstOrDefault(cachedRoute => cachedRoute.RawTemplate.Hash == rawTemplate.Hash);

                    if (existentCachedRoute != default)
                    {
                        _logger.LogDebug("Using cached {0} ({1})", rawTemplate.Name, rawTemplate.Hash);

                        mocks.Add(existentCachedRoute);

                        continue;
                    }

                    _logger.LogDebug("Loading {0} ({1})", rawTemplate.Name, rawTemplate.Hash);

                    var template = await _templateTransformer.Transform(rawTemplate, warmUpScriptContext);
                    var mock = CreateMock(rawTemplate, template.Request);

                    mocks.Add(mock);

                    _logger.LogInformation("{method} {route} mapped from {templateName}", template.Request?.Method, template.Request?.Route, rawTemplate.Name);
                }
                catch (JsonReaderException ex)
                {
                    _errors.Add((rawTemplate.Name, $"Generated JSON is invalid - {ex.Message}"));
                    
                    _logger.LogWarning("Skipping {0}: Generated JSON is invalid - {1}", rawTemplate.Name, ex.Message);
                }
                catch (ParserException ex)
                {
                    _errors.Add((rawTemplate.Name, $"Script parser error - {ex.Message} {ex.Location}"));

                    _logger.LogWarning("Skipping {0}: Script parser error - {1} {2} ", rawTemplate.Name, ex.Message, ex.Location);
                }
                catch (Exception ex)
                {
                    _errors.Add((rawTemplate.Name, ex.Message));

                    _logger.LogWarning("Skipping {0}: {1}", rawTemplate.Name, ex.Message);
                }
            }

            _cache.Clear();

            _cache = mocks.OrderByDescending(r => r.HasCondition).ToList();

            _healthCheck.StartupCompleted = true;

            _logger.LogTrace("{0} finished in {1} ms", nameof(WarmUp), stopwatch.ElapsedMilliseconds);
        }

        private static Mock CreateMock(IRawTemplate rawTemplate, RequestTemplate requestTemplate)
        {
            return new Mock(requestTemplate?.Method, requestTemplate?.Route, rawTemplate, requestTemplate?.Condition != default);
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Mockaco.AspNetCore.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">

	<PropertyGroup>
		<TargetFramework>net6.0</TargetFramework>
		<LangVersion>latest</LangVersion>
		<AssemblyName>Mockaco.AspNetCore</AssemblyName>
		<RootNamespace>Mockaco</RootNamespace>
		<ImplicitUsings>enable</ImplicitUsings>
		<Configurations>Debug;Release;Nuget</Configurations>
		<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
	</PropertyGroup>

	<PropertyGroup>
		<IsPackable>true</IsPackable>
		<PackageOutputPath>./nupkg</PackageOutputPath>
		<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
		<Authors>natenho</Authors>
		<Description>ASP.NET Core pipeline to mock HTTP requests/responses, useful to stub services and simulate dynamic API responses, leveraging ASP.NET Core features, built-in fake data generation and pure C# scripting</Description>
		<PackageProjectUrl>https://github.com/natenho/Mockaco</PackageProjectUrl>
		<RepositoryUrl>https://github.com/natenho/Mockaco</RepositoryUrl>
		<PackageTags>mock http aspnetcore</PackageTags>
		<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
		<PackageIcon>mockaco-icon.png</PackageIcon>
		<Product>Mockaco</Product>
	</PropertyGroup>

	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
		<NoWarn>1701;1702;NU5104</NoWarn>
		<WarningsNotAsErrors>AD0001;NU5104</WarningsNotAsErrors>
	</PropertyGroup>

	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
		<NoWarn>1701;1702;NU5104</NoWarn>
		<WarningsNotAsErrors>AD0001;NU5104</WarningsNotAsErrors>
	</PropertyGroup>

	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Nuget|AnyCPU'">
		<NoWarn>1701;1702;NU5104</NoWarn>
		<WarningsNotAsErrors>AD0001;NU5104</WarningsNotAsErrors>
	</PropertyGroup>

	<ItemGroup>
		<FrameworkReference Include="Microsoft.AspNetCore.App" />
	</ItemGroup>

	<ItemGroup>
		<PackageReference Include="Bogus" Version="34.0.2" />
		<PackageReference Include="GitVersion.MsBuild" Version="5.12.0">
			<PrivateAssets>all</PrivateAssets>
			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
		</PackageReference>
		<PackageReference Include="MAB.DotIgnore" Version="3.0.2" />
		<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.6.4" />
		<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.6.0" />
		<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.4">
			<PrivateAssets>all</PrivateAssets>
			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
		</PackageReference>
		<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
		<PackageReference Include="Polly" Version="7.2.3" />
		<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.21308.1" />
	</ItemGroup>

	<ItemGroup>
		<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
			<_Parameter1>Mockaco.Tests</_Parameter1>
		</AssemblyAttribute>
	</ItemGroup>

	<ItemGroup>
		<None Include="Resources\mockaco-icon.png">
			<Pack>True</Pack>
			<PackagePath>/</PackagePath>
		</None>
	</ItemGroup>

</Project>


================================================
FILE: src/Mockaco.AspNetCore/MockacoContext.cs
================================================
using System.Collections.Generic;

namespace Mockaco
{
    internal class MockacoContext : IMockacoContext
    {
        public IScriptContext ScriptContext { get; set; }

        public Template TransformedTemplate { get; set; }

        public Mock Mock { get; set; }

        public List<Error> Errors { get; set; }
                
        public MockacoContext(IScriptContext scriptContext)
        {
            ScriptContext = scriptContext;
            Errors = new List<Error>();
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Options/ChaosOptions.cs
================================================
namespace Mockaco;

public class ChaosOptions
{
    public bool Enabled { get; set; }
    public int ChaosRate { get; set; }
    public int MinimumLatencyTime { get; set; }
    public int MaximumLatencyTime { get; set; }
    public int TimeBeforeTimeout { get; set; }

    public ChaosOptions()
    {
        Enabled = false;
        ChaosRate = 10;
        MinimumLatencyTime = 500;
        MaximumLatencyTime = 3000;
        TimeBeforeTimeout = 10000;
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Options/MockacoOptions.cs
================================================
using System.Net;

namespace Mockaco
{
    public class MockacoOptions
    {
        public HttpStatusCode DefaultHttpStatusCode { get; set; }

        public HttpStatusCode ErrorHttpStatusCode { get; set; }       

        public string DefaultHttpContentType { get; set; }

        public List<string> References { get; set; }

        public List<string> VerificationIgnoredHeaders { get; set; }
        
        public List<string> Imports { get; set; }

        public int MatchedRoutesCacheDuration { get; set; }

        public string MockacoEndpoint { get; set; }

        // Deprecated (use MockacoEndpoint instead)
        public string VerificationEndpointPrefix { get; set; }
        
        public ChaosOptions Chaos { get; set; }

        public string VerificationEndpointName { get; set; }

        public TemplateFileProviderOptions TemplateFileProvider { get; set; }

        public MockacoOptions()
        {
            DefaultHttpStatusCode = HttpStatusCode.OK;
            ErrorHttpStatusCode = HttpStatusCode.NotImplemented;
            DefaultHttpContentType = HttpContentTypes.ApplicationJson;
            References = new List<string>();
            Imports = new List<string>();
            MatchedRoutesCacheDuration = 60;
            MockacoEndpoint = "_mockaco";
            VerificationEndpointName = "verification";
            TemplateFileProvider = new();
            Chaos = new ChaosOptions();
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Options/TemplateFileProviderOptions.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Mockaco
{
    public class TemplateFileProviderOptions
    {
        public string Path { get; set; }

        public TemplateFileProviderOptions()
        {
            Path = "Mocks";
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Plugins/PhoneNumberExtensions.cs
================================================
using Bogus.DataSets;

namespace Bogus
{
    // TODO Move to plugin
    public static class PhoneNumberExtensions
    {
        public static string BrazilianPhoneNumber(this PhoneNumbers phoneNumbers)
        {
            var faker = new Faker("pt_BR");
            string[] brazilianAreaCodes = { "11", "12", "13", "14", "15", "16", "17", "18", "19", "21", "22", "24", "27", "28", "31", "32", "33", "34", "35", "37", "38", "41", "42", "43", "44", "45", "46", "47", "48", "49", "51", "53", "54", "55", "61", "62", "63", "64", "65", "66", "67", "68", "69", "71", "73", "74", "75", "77", "79", "81", "82", "83", "84", "85", "86", "87", "88", "89", "91", "92", "93", "94", "95", "96", "97", "98", "99" };
            var areaCode = faker.PickRandom(brazilianAreaCodes);
            var sufix = faker.Random.Number(50000000, 99999999);
            return $"{areaCode}9{sufix}";
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/PublicAPI.Shipped.txt
================================================


================================================
FILE: src/Mockaco.AspNetCore/PublicAPI.Unshipped.txt
================================================
Bogus.PhoneNumberExtensions
Microsoft.AspNetCore.Builder.MockacoApplicationBuilder
Microsoft.Extensions.DependencyInjection.MockacoServiceCollection
Mockaco.ChaosOptions
Mockaco.ChaosOptions.ChaosOptions() -> void
Mockaco.ChaosOptions.ChaosRate.get -> int
Mockaco.ChaosOptions.ChaosRate.set -> void
Mockaco.ChaosOptions.Enabled.get -> bool
Mockaco.ChaosOptions.Enabled.set -> void
Mockaco.ChaosOptions.MaximumLatencyTime.get -> int
Mockaco.ChaosOptions.MaximumLatencyTime.set -> void
Mockaco.ChaosOptions.MinimumLatencyTime.get -> int
Mockaco.ChaosOptions.MinimumLatencyTime.set -> void
Mockaco.ChaosOptions.TimeBeforeTimeout.get -> int
Mockaco.ChaosOptions.TimeBeforeTimeout.set -> void
Mockaco.HealthChecks.StartupHealthCheck
Mockaco.HealthChecks.StartupHealthCheck.CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult>
Mockaco.HealthChecks.StartupHealthCheck.StartupCompleted.get -> bool
Mockaco.HealthChecks.StartupHealthCheck.StartupCompleted.set -> void
Mockaco.HealthChecks.StartupHealthCheck.StartupHealthCheck() -> void
Mockaco.IFakerFactory
Mockaco.IFakerFactory.GetDefaultFaker() -> Bogus.Faker
Mockaco.IFakerFactory.GetFaker(System.Collections.Generic.IEnumerable<string> acceptLanguages) -> Bogus.Faker
Mockaco.IGlobalVariableStorage
Mockaco.IGlobalVariableStorage.Clear() -> void
Mockaco.IGlobalVariableStorage.DisableWriting() -> void
Mockaco.IGlobalVariableStorage.EnableWriting() -> void
Mockaco.IGlobalVariableStorage.this[string name].get -> object
Mockaco.IGlobalVariableStorage.this[string name].set -> void
Mockaco.IRawTemplate
Mockaco.IRawTemplate.Content.get -> string
Mockaco.IRawTemplate.Hash.get -> string
Mockaco.IRawTemplate.Name.get -> string
Mockaco.IRequestBodyFactory
Mockaco.IRequestBodyFactory.ReadBodyAsJson(Microsoft.AspNetCore.Http.HttpRequest httpRequest) -> System.Threading.Tasks.Task<Newtonsoft.Json.Linq.JToken>
Mockaco.IScriptContext
Mockaco.IScriptContext.AttachRequest(Microsoft.AspNetCore.Http.HttpRequest httpRequest) -> System.Threading.Tasks.Task
Mockaco.IScriptContext.AttachResponse(Microsoft.AspNetCore.Http.HttpResponse httpResponse, Mockaco.ResponseTemplate responseTemplate) -> System.Threading.Tasks.Task
Mockaco.IScriptContext.AttachRouteParameters(Microsoft.AspNetCore.Http.HttpRequest httpRequest, Mockaco.Mock route) -> System.Threading.Tasks.Task
Mockaco.IScriptContext.Faker.get -> Bogus.Faker
Mockaco.IScriptContext.Global.get -> Mockaco.IGlobalVariableStorage
Mockaco.IScriptContext.Request.get -> Mockaco.ScriptContextRequest
Mockaco.IScriptContext.Request.set -> void
Mockaco.IScriptContext.Response.get -> Mockaco.ScriptContextResponse
Mockaco.IScriptContext.Response.set -> void
Mockaco.Mock
Mockaco.Mock.HasCondition.get -> bool
Mockaco.Mock.HasCondition.set -> void
Mockaco.Mock.Method.get -> string
Mockaco.Mock.Method.set -> void
Mockaco.Mock.Mock(string method, string route, Mockaco.IRawTemplate rawTemplate, bool hasCondition) -> void
Mockaco.Mock.RawTemplate.get -> Mockaco.IRawTemplate
Mockaco.Mock.RawTemplate.set -> void
Mockaco.Mock.Route.get -> string
Mockaco.Mock.Route.set -> void
Mockaco.MockacoOptions
Mockaco.MockacoOptions.Chaos.get -> Mockaco.ChaosOptions
Mockaco.MockacoOptions.Chaos.set -> void
Mockaco.MockacoOptions.DefaultHttpContentType.get -> string
Mockaco.MockacoOptions.DefaultHttpContentType.set -> void
Mockaco.MockacoOptions.DefaultHttpStatusCode.get -> System.Net.HttpStatusCode
Mockaco.MockacoOptions.DefaultHttpStatusCode.set -> void
Mockaco.MockacoOptions.ErrorHttpStatusCode.get -> System.Net.HttpStatusCode
Mockaco.MockacoOptions.ErrorHttpStatusCode.set -> void
Mockaco.MockacoOptions.VerificationIgnoredHeaders.get -> System.Collections.Generic.List<string>
Mockaco.MockacoOptions.VerificationIgnoredHeaders.set -> void
Mockaco.MockacoOptions.Imports.get -> System.Collections.Generic.List<string>
Mockaco.MockacoOptions.Imports.set -> void
Mockaco.MockacoOptions.MatchedRoutesCacheDuration.get -> int
Mockaco.MockacoOptions.MatchedRoutesCacheDuration.set -> void
Mockaco.MockacoOptions.MockacoEndpoint.get -> string
Mockaco.MockacoOptions.MockacoEndpoint.set -> void
Mockaco.MockacoOptions.MockacoOptions() -> void
Mockaco.MockacoOptions.References.get -> System.Collections.Generic.List<string>
Mockaco.MockacoOptions.References.set -> void
Mockaco.MockacoOptions.TemplateFileProvider.get -> Mockaco.TemplateFileProviderOptions
Mockaco.MockacoOptions.TemplateFileProvider.set -> void
Mockaco.MockacoOptions.VerificationEndpointName.get -> string
Mockaco.MockacoOptions.VerificationEndpointName.set -> void
Mockaco.MockacoOptions.VerificationEndpointPrefix.get -> string
Mockaco.MockacoOptions.VerificationEndpointPrefix.set -> void
Mockaco.ResponseTemplate
Mockaco.ResponseTemplate.Body.get -> Newtonsoft.Json.Linq.JToken
Mockaco.ResponseTemplate.Body.set -> void
Mockaco.ResponseTemplate.Delay.get -> int?
Mockaco.ResponseTemplate.Delay.set -> void
Mockaco.ResponseTemplate.File.get -> string
Mockaco.ResponseTemplate.File.set -> void
Mockaco.ResponseTemplate.Headers.get -> System.Collections.Generic.IDictionary<string, string>
Mockaco.ResponseTemplate.Headers.set -> void
Mockaco.ResponseTemplate.Indented.get -> bool?
Mockaco.ResponseTemplate.Indented.set -> void
Mockaco.ResponseTemplate.ResponseTemplate() -> void
Mockaco.ResponseTemplate.Status.get -> System.Net.HttpStatusCode
Mockaco.ResponseTemplate.Status.set -> void
Mockaco.ScriptContext
Mockaco.ScriptContext.AttachRequest(Microsoft.AspNetCore.Http.HttpRequest httpRequest) -> System.Threading.Tasks.Task
Mockaco.ScriptContext.AttachResponse(Microsoft.AspNetCore.Http.HttpResponse httpResponse, Mockaco.ResponseTemplate responseTemplate) -> System.Threading.Tasks.Task
Mockaco.ScriptContext.AttachRouteParameters(Microsoft.AspNetCore.Http.HttpRequest httpRequest, Mockaco.Mock mock) -> System.Threading.Tasks.Task
Mockaco.ScriptContext.Faker.get -> Bogus.Faker
Mockaco.ScriptContext.Global.get -> Mockaco.IGlobalVariableStorage
Mockaco.ScriptContext.Request.get -> Mockaco.ScriptContextRequest
Mockaco.ScriptContext.Request.set -> void
Mockaco.ScriptContext.Response.get -> Mockaco.ScriptContextResponse
Mockaco.ScriptContext.Response.set -> void
Mockaco.ScriptContext.ScriptContext(Mockaco.IFakerFactory fakerFactory, Mockaco.IRequestBodyFactory requestBodyFactory, Mockaco.IGlobalVariableStorage globalVarialeStorage) -> void
Mockaco.ScriptContextRequest
Mockaco.ScriptContextRequest.Body.get -> Newtonsoft.Json.Linq.JToken
Mockaco.ScriptContextRequest.Header.get -> System.Collections.Generic.IReadOnlyDictionary<string, string>
Mockaco.ScriptContextRequest.Query.get -> System.Collections.Generic.IReadOnlyDictionary<string, string>
Mockaco.ScriptContextRequest.Route.get -> System.Collections.Generic.IReadOnlyDictionary<string, string>
Mockaco.ScriptContextRequest.ScriptContextRequest(System.Uri url, System.Collections.Generic.IReadOnlyDictionary<string, string> route, System.Collections.Generic.IReadOnlyDictionary<string, string> query, System.Collections.Generic.IReadOnlyDictionary<string, string> header, Newtonsoft.Json.Linq.JToken body) -> void
Mockaco.ScriptContextRequest.Url.get -> System.Uri
Mockaco.ScriptContextResponse
Mockaco.ScriptContextResponse.Body.get -> Newtonsoft.Json.Linq.JToken
Mockaco.ScriptContextResponse.Header.get -> System.Collections.Generic.IReadOnlyDictionary<string, string>
Mockaco.ScriptContextResponse.ScriptContextResponse(Mockaco.StringDictionary header, Newtonsoft.Json.Linq.JToken body) -> void
Mockaco.StringDictionary
Mockaco.StringDictionary.Add(string key, string value) -> void
Mockaco.StringDictionary.Replace(string key, string value) -> void
Mockaco.StringDictionary.StringDictionary() -> void
Mockaco.StringDictionary.this[string key].get -> string
Mockaco.StringDictionary.this[string key].set -> void
Mockaco.TemplateFileProviderOptions
Mockaco.TemplateFileProviderOptions.Path.get -> string
Mockaco.TemplateFileProviderOptions.Path.set -> void
Mockaco.TemplateFileProviderOptions.TemplateFileProviderOptions() -> void
override Mockaco.Mock.ToString() -> string
static Bogus.PhoneNumberExtensions.BrazilianPhoneNumber(this Bogus.DataSets.PhoneNumbers phoneNumbers) -> string
static Microsoft.AspNetCore.Builder.MockacoApplicationBuilder.UseMockaco(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) -> Microsoft.AspNetCore.Builder.IApplicationBuilder
static Microsoft.AspNetCore.Builder.MockacoApplicationBuilder.UseMockaco(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, System.Action<Microsoft.AspNetCore.Builder.IApplicationBuilder> configure) -> Microsoft.AspNetCore.Builder.IApplicationBuilder
static Microsoft.Extensions.DependencyInjection.MockacoServiceCollection.AddMockaco(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection
static Microsoft.Extensions.DependencyInjection.MockacoServiceCollection.AddMockaco(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, Microsoft.Extensions.Configuration.IConfiguration config) -> Microsoft.Extensions.DependencyInjection.IServiceCollection
static Microsoft.Extensions.DependencyInjection.MockacoServiceCollection.AddMockaco(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<Mockaco.MockacoOptions> config) -> Microsoft.Extensions.DependencyInjection.IServiceCollection


================================================
FILE: src/Mockaco.AspNetCore/Settings/VerificationRouteValueTransformer.cs
================================================
namespace Mockaco.Settings
{
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc.Routing;
    using Microsoft.AspNetCore.Routing;

    internal class VerificationRouteValueTransformer : DynamicRouteValueTransformer
    {
        public override ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values)
        {
            values["controller"] = "verify";
            values["action"] = "Get";

            return ValueTask.FromResult(values);
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Cli/GeneratorRunner.cs
================================================
using System;
using System.CommandLine;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace Mockaco.Templating.Generating.Cli
{
    internal class GeneratorRunner
    {
        private readonly IServiceProvider _serviceProvider;

        public GeneratorRunner(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public async Task<int> ExecuteAsync(GeneratingOptions options, IConsole console, CancellationToken cancellationToken)
        {
            using var scope = _serviceProvider.CreateScope();
            await scope.ServiceProvider.GetRequiredService<TemplatesGenerator>().GenerateAsync(options, cancellationToken);
            return 0;
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/GeneratedTemplate.cs
================================================
namespace Mockaco.Templating.Generating
{
    internal class GeneratedTemplate : Template
    {
        public string Name { get; set; }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/GeneratingOptions.cs
================================================
using System;
using System.IO;

namespace Mockaco.Templating.Generating
{
    internal class GeneratingOptions
    {
        public string Source { get; set; }

        public Uri SourceUri
        {
            get
            {
                if (Uri.TryCreate(Source, UriKind.Absolute, out Uri uri))
                {
                    return uri;
                }
                else if (Path.IsPathFullyQualified(Source))
                {
                    return new Uri(new Uri(Uri.UriSchemeFile), Source);
                }
                else
                {
                    throw new ArgumentException("Provided Source cannot be converted to Uri");
                }
            }
        }

        public string Provider { get; set; }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Providers/GeneratedTemplateProviderFactory.cs
================================================
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;

namespace Mockaco.Templating.Generating.Providers
{
    internal class GeneratedTemplateProviderFactory : IGeneratedTemplateProviderFactory
    {
        private readonly IServiceProvider _serviceProvider;

        private readonly IDictionary<string, Type> _providersRegistry = new Dictionary<string, Type>
        {
            {"openapi", typeof(OpenApiTemplateProvider)}
        };

        public GeneratedTemplateProviderFactory(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
        
        public IGeneratedTemplateProvider Create(string providerType)
        {
            if (_providersRegistry.ContainsKey(providerType))
            {
                return (IGeneratedTemplateProvider)_serviceProvider.GetRequiredService(_providersRegistry[providerType]);
            }

            throw new NotSupportedException($"Provider {providerType} is not supported.");
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Providers/IGeneratedTemplateProvider.cs
================================================
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Mockaco.Templating.Generating.Providers
{
    internal interface IGeneratedTemplateProvider
    {
        Task<IEnumerable<GeneratedTemplate>> GetTemplatesAsync(Stream sourceStream, CancellationToken cancellationToken = default);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Providers/IGeneratedTemplateProviderFactory.cs
================================================
namespace Mockaco.Templating.Generating.Providers
{
    internal interface IGeneratedTemplateProviderFactory
    {
        IGeneratedTemplateProvider Create(string providerType);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Providers/OpenApiTemplateProvider.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Readers;
using Newtonsoft.Json.Linq;

namespace Mockaco.Templating.Generating.Providers
{
    internal class OpenApiTemplateProvider : IGeneratedTemplateProvider
    {
        private readonly ILogger _logger;

        public OpenApiTemplateProvider(ILogger<OpenApiTemplateProvider> logger)
        {
            _logger = logger;
        }
        
        public Task<IEnumerable<GeneratedTemplate>> GetTemplatesAsync(Stream sourceStream, CancellationToken cancellationToken = default)
        {
            
            var openApiDocument = new OpenApiStreamReader(
                    new OpenApiReaderSettings
                    {
                        ReferenceResolution = ReferenceResolutionSetting.ResolveLocalReferences
                    }
                )
                .Read(sourceStream, out var diagnostic);
            
            LogDiagnostics(diagnostic);

            return Task.FromResult(BuildTemplates(openApiDocument));
        }

        private IEnumerable<GeneratedTemplate> BuildTemplates(OpenApiDocument openApiDocument)
        {
            foreach (var path in openApiDocument.Paths)
            {
                foreach (var operation in path.Value.Operations)
                {
                    var template = new GeneratedTemplate
                    {
                        Request = BuildRequest(path, operation),
                        Response = BuildResponse(operation)
                    };

                    SetTemplateName(template, operation);
                    yield return template;
                }
            }
        }

        private void SetTemplateName(GeneratedTemplate template, KeyValuePair<OperationType, OpenApiOperation> operation)
        {
            template.Name = operation.Value.OperationId;
            if (string.IsNullOrWhiteSpace(template.Name))
            {
                template.Name = Guid.NewGuid().ToString("N");
                _logger.LogWarning(
                    "The OperationId for request {Method} {Route} hasn't been declared. Using generated template name: {TemplateName}",
                    template.Request.Method, template.Request.Route, template.Name);
            }
        }

        private ResponseTemplate BuildResponse(KeyValuePair<OperationType,OpenApiOperation> operation)
        {
            var responseTemplate = new ResponseTemplate();
            if (operation.Value.Responses.Any())
            {
                var response = operation.Value.Responses.First();
                responseTemplate.Status = (HttpStatusCode) int.Parse(response.Key);
                if (response.Value.Content.Any())
                {
                    var content = response.Value.Content.First();
                    responseTemplate.Headers.Add("Content-Type", content.Key);
                    if (content.Value.Example != null)
                    {
                        responseTemplate.Body = JValue.CreateString(content.Value.Example.ToString());
                    }
                }
            }
            else
            {
                responseTemplate.Status = HttpStatusCode.NotFound;
            }
            return responseTemplate;
        }

        private RequestTemplate BuildRequest(KeyValuePair<string,OpenApiPathItem> path, KeyValuePair<OperationType,OpenApiOperation> operation)
        {
            return new RequestTemplate
            {
                Route = path.Key,
                Method = Enum.GetName(operation.Key)?.ToUpper()
            };
        }

        private void LogDiagnostics(OpenApiDiagnostic diagnostic)
        {
            _logger.LogDebug("OpenApi specification version: {OpenApiSpecVersion}", Enum.GetName(diagnostic.SpecificationVersion));
            foreach (var diagnosticError in diagnostic.Errors)
            {
                _logger.LogWarning("OpenApi parser diagnostic error: {Error}", diagnosticError);
            }
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/ServiceCollectionExtensions.cs
================================================
using Mockaco.Templating.Generating;
using Mockaco.Templating.Generating.Cli;
using Mockaco.Templating.Generating.Providers;
using Mockaco.Templating.Generating.Source;
using Mockaco.Templating.Generating.Store;
using System.CommandLine;
using System.CommandLine.Invocation;

namespace Microsoft.Extensions.DependencyInjection
{
    internal static class ServiceCollectionExtensions
    {
        public static IServiceCollection AddTemplatesGenerating(this IServiceCollection services)
        {
            services
                .AddTransient<IGeneratedTemplateStore, GeneratedTemplateStore>()
                .AddTransient<ISourceContentProvider, SourceContentProviderComposite>()
                .AddTransient<IGeneratedTemplateProviderFactory, GeneratedTemplateProviderFactory>()
                .AddTransient<OpenApiTemplateProvider>()
                .AddTransient<TemplatesGenerator>();
            
            services.AddOptions<TemplateStoreOptions>()
                    .Configure(options =>
                    {
                        options.RootDir = "Mocks";
                    })
                    .BindConfiguration("Mockaco:TemplateFileProvider:Path");

            services.AddTransient<GeneratorRunner>();
            services.AddTransient(provider =>
            {
                var cmd = new Command("generate")
                {
                    new Argument<string>("source"),
                    new Option<string>(new[] { "--provider"})
                    {
                        IsRequired = true
                    },
                    new Option<string>("--path")
                };

                cmd.Handler = CommandHandler.Create<GeneratingOptions, IConsole, CancellationToken>(
                    provider.GetRequiredService<GeneratorRunner>().ExecuteAsync);
                
                return cmd;
            });
            
            return services;
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Source/HttpContentProvider.cs
================================================
using System;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace Mockaco.Templating.Generating.Source
{
    internal class HttpContentProvider : ISourceContentProvider
    {
        public async Task<Stream> GetStreamAsync(Uri sourceUri, CancellationToken cancellationToken)
        {
            return await new HttpClient().GetStreamAsync(sourceUri, cancellationToken);
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Source/ISourceContentProvider.cs
================================================
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Mockaco.Templating.Generating.Source
{
    internal interface ISourceContentProvider
    {
        Task<Stream> GetStreamAsync(Uri sourceUri, CancellationToken cancellationToken);
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Source/LocalFileContentProvider.cs
================================================
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Mockaco.Templating.Generating.Source
{
    internal class LocalFileContentProvider : ISourceContentProvider
    {
        public Task<Stream> GetStreamAsync(Uri sourceUri, CancellationToken cancellationToken)
        {
            return Task.FromResult((Stream)File.OpenRead(sourceUri.LocalPath));
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Source/SourceContentProviderComposite.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace Mockaco.Templating.Generating.Source
{
    internal class SourceContentProviderComposite : ISourceContentProvider
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly IDictionary<Predicate<Uri>, Type> _providersRegistry = new Dictionary<Predicate<Uri>, Type>();

        public SourceContentProviderComposite(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
            RegisterDefaultProviders();
        }

        private void RegisterDefaultProviders()
        {
            Register(uri => uri.Scheme.Equals(Uri.UriSchemeFile) || Path.IsPathFullyQualified(uri.OriginalString), typeof(LocalFileContentProvider));
            Register(uri => uri.Scheme.Equals(Uri.UriSchemeHttp) || uri.Scheme.Equals(Uri.UriSchemeHttps), typeof(HttpContentProvider));
        }

        private ISourceContentProvider Create(Uri sourceUri)
        {
            foreach (var registryItem in _providersRegistry)
            {
                var canHandle = registryItem.Key;
                var providerType = registryItem.Value;

                if (canHandle(sourceUri))
                {
                    return (ISourceContentProvider)Activator.CreateInstance(registryItem.Value);
                }
            }

            throw new NotSupportedException("Specified URI is not supported");
        }

        public void Register(Predicate<Uri> canHandle, Type type)
        {
            _providersRegistry.Add(canHandle, type);
        }

        public Task<Stream> GetStreamAsync(Uri sourceUri, CancellationToken cancellationToken)
        {
            var specificProvider = Create(sourceUri);
            return specificProvider.GetStreamAsync(sourceUri, cancellationToken);
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Store/GeneratedTemplateStore.cs
================================================
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Mockaco.Templating.Generating.Store
{
    internal class GeneratedTemplateStore : IGeneratedTemplateStore
    {
        private const string FileExtension = ".json";
        
        private readonly IOptions<TemplateStoreOptions> _options;
        private readonly ILogger _logger;

        public GeneratedTemplateStore(IOptions<TemplateStoreOptions> options, ILogger<GeneratedTemplateStore> logger)
        {
            _options = options;
            _logger = logger;
        }

        private string RootDir => _options.Value.RootDir;

        public async Task SaveAsync(GeneratedTemplate template, CancellationToken cancellationToken = default)
        {
            var templateFileName = GetFileName(template);
            Directory.CreateDirectory(Path.GetDirectoryName(templateFileName) ?? string.Empty);
            await File.WriteAllBytesAsync(templateFileName, GetTemplateContent(template), cancellationToken);

            _logger.LogInformation("Generated {template} for {method} {route}", templateFileName, template.Request.Method, template.Request.Route);
        }

        private byte[] GetTemplateContent(GeneratedTemplate template)
        {
            return JsonSerializer.SerializeToUtf8Bytes<Template>(template, new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                WriteIndented = true,
                DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
            });
        }

        public async Task SaveAsync(IEnumerable<GeneratedTemplate> templates, CancellationToken cancellationToken = default)
        {
            foreach (var template in templates)
            {
                if (!cancellationToken.IsCancellationRequested)
                    await SaveAsync(template, cancellationToken);
                else break;
            }
        }

        private string GetFileName(GeneratedTemplate template)
        {
            var fileName = template.Name;
            if (!fileName.EndsWith(FileExtension))
            {
                fileName += FileExtension;
            }
            
            return fileName.StartsWith(RootDir) ? fileName : Path.Combine(RootDir, fileName);
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Store/IGeneratedTemplateStore.cs
================================================
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Mockaco.Templating.Generating.Store
{
    internal interface IGeneratedTemplateStore
    {
        Task SaveAsync(GeneratedTemplate template, CancellationToken cancellationToken = default);
        
        Task SaveAsync(IEnumerable<GeneratedTemplate> templates, CancellationToken cancellationToken = default);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/Store/TemplateStoreOptions.cs
================================================
namespace Mockaco.Templating.Generating.Store
{
    internal class TemplateStoreOptions
    {
        public string RootDir { get; set; }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Generating/TemplatesGenerator.cs
================================================
using System.Threading;
using System.Threading.Tasks;
using Mockaco.Templating.Generating.Providers;
using Mockaco.Templating.Generating.Source;
using Mockaco.Templating.Generating.Store;

namespace Mockaco.Templating.Generating
{
    internal class TemplatesGenerator
    {
        private readonly ISourceContentProvider _sourceContentProvider;
        private readonly IGeneratedTemplateProviderFactory _providerFactory;
        private readonly IGeneratedTemplateStore _templateStore;

        public TemplatesGenerator(ISourceContentProvider sourceContentProvider, IGeneratedTemplateProviderFactory providerFactory, IGeneratedTemplateStore templateStore)
        {
            _sourceContentProvider = sourceContentProvider;
            _providerFactory = providerFactory;
            _templateStore = templateStore;
        }
        
        public async Task GenerateAsync(GeneratingOptions options, CancellationToken cancellationToken = default)
        {
            var sourceStream = await _sourceContentProvider.GetStreamAsync(options.SourceUri, cancellationToken);
            var templates = await _providerFactory.Create(options.Provider).GetTemplatesAsync(sourceStream, cancellationToken);
            await _templateStore.SaveAsync(templates, cancellationToken);
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/ITemplateTransformer.cs
================================================
using System.Threading.Tasks;

namespace Mockaco
{
    internal interface ITemplateTransformer
    {
        //TODO Improve this abstraction
        Task<Template> TransformAndSetVariables(IRawTemplate rawTemplate, IScriptContext scriptContext);

        Task<Template> Transform(IRawTemplate rawTemplate, IScriptContext scriptContext);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Models/CallbackTemplate.cs
================================================
using Newtonsoft.Json.Linq;
using System.Collections.Generic;

namespace Mockaco
{
    internal class CallbackTemplate
    {
        public string Method { get; set; }

        public string Url { get; set; }

        public int? Delay { get; set; }

        public int? Timeout { get; set; }

        public bool? Indented { get; set; }

        public IDictionary<string, string> Headers { get; set; }

        public JToken Body { get; set; }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Models/Error.cs
================================================
using System;

namespace Mockaco
{
    internal class Error
    {
        public string Message { get; }

        public Exception Exception { get; }

        public Error(string message)
        {
            Message = message;
        }

        public Error(Exception exception)
        {
            Exception = exception;
        }

        public Error(string message, Exception exception)
        {
            Message = message;
            Exception = exception;
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Models/IRawTemplate.cs
================================================
namespace Mockaco
{
    public interface IRawTemplate
    {
        string Content { get; }

        string Name { get; }

        string Hash { get; }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Models/Mock.cs
================================================
using System.Diagnostics;

namespace Mockaco
{
    [DebuggerDisplay("{Method} {Route} ({RawTemplate.Name})")]
    public class Mock
    {
        public string Method { get; set; }

        public string Route { get; set; }

        public IRawTemplate RawTemplate { get; set; }

        public bool HasCondition { get; set; }

        public Mock(string method, string route, IRawTemplate rawTemplate, bool hasCondition)
        {
            Method = method;
            Route = route;
            RawTemplate = rawTemplate;
            HasCondition = hasCondition;
        }

        public override string ToString()
        {
            return $"{Method} {Route} ({RawTemplate.Name})";
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Models/RawTemplate.cs
================================================
using System;
using System.Diagnostics;

namespace Mockaco
{
    [DebuggerDisplay("{Name}")]
    internal class RawTemplate : IRawTemplate
    {
        public string Name { get; }

        public string Content { get; }

        public string Hash { get; }

        public RawTemplate(string name, string content)
        {
            Name = name;
            Content = content;
            Hash = content.ToMD5Hash();
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Models/RequestTemplate.cs
================================================
namespace Mockaco
{
    internal class RequestTemplate
    {
        public string Method { get; set; }

        public string Route { get; set; }

        public bool? Condition { get; set; }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Models/ResponseTemplate.cs
================================================
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Net;

namespace Mockaco
{
    public class ResponseTemplate
    {
        public int? Delay { get; set; }

        public bool? Indented { get; set; }

        public HttpStatusCode Status { get; set; }

        public IDictionary<string, string> Headers { get; set; }

        public JToken Body { get; set; }

        public string File { get; set; }

        public ResponseTemplate()
        {
            Headers = new StringDictionary();
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Models/Template.cs
================================================
using System.Collections.Generic;
using System.Linq;

namespace Mockaco
{
    internal class Template
    {
        public Template()
        {
            Callbacks = Enumerable.Empty<CallbackTemplate>();
        }

        public RequestTemplate Request { get; set; }

        public ResponseTemplate Response { get; set; }

        public CallbackTemplate Callback
        {
            get => Callbacks.Count() == 1 ? Callbacks.First() : default;
            set => Callbacks = new[] { value };
        }

        public IEnumerable<CallbackTemplate> Callbacks { get; set; }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Providers/ITemplateProvider.cs
================================================
using System;
using System.Collections.Generic;

namespace Mockaco
{
    internal interface ITemplateProvider
    {
        event EventHandler OnChange;

        IEnumerable<IRawTemplate> GetTemplates();
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Providers/TemplateFileProvider.cs
================================================
using MAB.DotIgnore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.FileProviders.Physical;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Polly;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;

namespace Mockaco
{
    internal sealed class TemplateFileProvider : ITemplateProvider, IDisposable
    {
        public event EventHandler OnChange;

        private const string MockIgnoreFileName = ".mockignore";
        private const string DefaultTemplateSearchPattern = "*.json";

        private readonly ILogger<TemplateFileProvider> _logger;
        
        private readonly IMemoryCache _memoryCache;
        private PhysicalFileProvider _fileProvider;
        private CancellationTokenSource _resetCacheToken = new CancellationTokenSource();

        public TemplateFileProvider(IOptionsMonitor<TemplateFileProviderOptions> options, IWebHostEnvironment webHostEnvironment, IMemoryCache memoryCache, ILogger<TemplateFileProvider> logger)
        {            
            _memoryCache = memoryCache;
            _logger = logger;

            SetMockRootPath(options.CurrentValue.Path);
            KeepWatchingForFileChanges();

            options.OnChange(options => {
                SetMockRootPath(options.Path);
                ResetCacheAndNotifyChange();
            });
        }

        private void SetMockRootPath(string path)
        {
            try
            {
                if(_fileProvider?.Root.Equals(path) == true)
                {
                    return;
                }

                var fullPath = Path.IsPathRooted(path) 
                    ? path 
                    : Path.Combine(Directory.GetCurrentDirectory(), path);

                if (!Directory.Exists(fullPath))
                {
                    Directory.CreateDirectory(fullPath);
                }

                var fileProvider = new PhysicalFileProvider(fullPath, ExclusionFilters.Hidden | ExclusionFilters.System);

                _fileProvider?.Dispose();
                _fileProvider = fileProvider;

                _logger.LogInformation("Mock path: {fullPath}", fullPath);
            }            
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error setting mock root path");
            }
        }

        private void ResetCacheAndNotifyChange()
        {
            FlushCache();
            GetTemplates();

            OnChange?.Invoke(this, EventArgs.Empty);

            KeepWatchingForFileChanges();
        }

        private void KeepWatchingForFileChanges()
        {
            if(_fileProvider == null)
            {
                return;
            }

            var jsonChangeToken = _fileProvider.Watch($"**/{DefaultTemplateSearchPattern}");
            jsonChangeToken.RegisterChangeCallback(TemplateFileModified, default);

            var mockIgnoreChangeToken = _fileProvider.Watch($"**/*{MockIgnoreFileName}");
            mockIgnoreChangeToken.RegisterChangeCallback(TemplateFileModified, default);
        }

        private void TemplateFileModified(object state)
        {
            _logger.LogInformation("File change detected");

            ResetCacheAndNotifyChange();
        }

        public IEnumerable<IRawTemplate> GetTemplates()
        {
            return _memoryCache.GetOrCreate(
                nameof(TemplateFileProvider),
                e =>
                {
                    e.RegisterPostEvictionCallback(PostEvictionCallback);
                    e.AddExpirationToken(new CancellationChangeToken(_resetCacheToken.Token));

                    return LoadTemplatesFromDirectory();
                });
        }

        private void PostEvictionCallback(object key, object value, EvictionReason reason, object state)
        {
            _logger.LogDebug("Mock files cache invalidated because of {reason}", reason);
        }

        private IEnumerable<IRawTemplate> LoadTemplatesFromDirectory()
        {
            if(_fileProvider == null)
            {
                yield break;
            }

            var directory = new DirectoryInfo(_fileProvider.Root);

            foreach (var file in directory.GetFiles(DefaultTemplateSearchPattern, SearchOption.AllDirectories)
                                .OrderBy(f => f.FullName))
            {
                var relativeFilePath = Path.GetRelativePath(_fileProvider.Root, file.FullName);

                if (ShouldIgnoreFile(file))
                {
                    _logger.LogDebug("{relativeFilePath} ignored using a {MockIgnoreFileName} file", relativeFilePath, MockIgnoreFileName);
                    continue;
                }

                var name = Path.GetRelativePath(directory.FullName, file.FullName);
                var rawContent = string.Empty;

                var rawTemplate = WrapWithFileExceptionHandling(relativeFilePath, () =>
                {
                    using var stream = File.Open(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
                    using var streamReader = new StreamReader(stream);
                    rawContent = streamReader.ReadToEnd();
                    return new RawTemplate(name, rawContent);
                });

                if (rawTemplate != default)
                {
                    yield return rawTemplate;
                }
            }
        }

        private bool ShouldIgnoreFile(FileInfo file)
        {
            var mockIgnorePath = Path.Combine(file.DirectoryName, MockIgnoreFileName);

            if (!File.Exists(mockIgnorePath))
            {
                return false;
            }

            var ignores = WrapWithFileExceptionHandling(mockIgnorePath, () =>
            {
                return new IgnoreList(mockIgnorePath);
            });

            if (ignores == default)
            {
                return false;
            }

            return ignores.IsIgnored(file);
        }

        private T WrapWithFileExceptionHandling<T>(string path, Func<T> action)
        {
            void log(Exception ex) => _logger.LogWarning("Could not load {path} due to {exceptionType}: {exceptionMessage}", path, ex.GetType(), ex.Message);

            try
            {
                return Policy.Handle<IOException>()
                        .WaitAndRetry(sleepDurations: new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) },
                                      onRetry: (ex, _) => log(ex))
                        .Execute(action);
            }
            catch (Exception ex)
            {
                log(ex);
            }

            return default;
        }

        private void FlushCache()
        {
            if (_resetCacheToken?.IsCancellationRequested == false && _resetCacheToken.Token.CanBeCanceled)
            {
                _resetCacheToken.Cancel();
                _resetCacheToken.Dispose();
            }

            _resetCacheToken = new CancellationTokenSource();
        }

        public void Dispose()
        {
            _fileProvider?.Dispose();
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Request/FormRequestBodyStrategy.cs
================================================
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;
using System.Linq;
using System.Threading.Tasks;

namespace Mockaco
{
    internal class FormRequestBodyStrategy : IRequestBodyStrategy
    {
        public bool CanHandle(HttpRequest httpRequest)
        {
            return httpRequest.HasFormContentType;
        }

        public Task<JToken> ReadBodyAsJson(HttpRequest httpRequest)
        {
            return Task.FromResult(JToken.FromObject(httpRequest.Form.ToDictionary(f => f.Key, f => f.Value.ToString())));
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Request/IRequestBodyFactory.cs
================================================
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;

namespace Mockaco
{
    public interface IRequestBodyFactory
    {
        Task<JToken> ReadBodyAsJson(HttpRequest httpRequest);
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Request/IRequestBodyStrategy.cs
================================================
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;

namespace Mockaco
{
    internal interface IRequestBodyStrategy
    {
        bool CanHandle(HttpRequest httpRequest);
        Task<JToken> ReadBodyAsJson(HttpRequest httpRequest);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Request/IRequestMatcher.cs
================================================
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

namespace Mockaco
{
    internal interface IRequestMatcher
    {
        Task<bool> IsMatch(HttpRequest httpRequest, Mock mock);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Request/JsonRequestBodyStrategy.cs
================================================

using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;


namespace Mockaco
{
    internal class JsonRequestBodyStrategy: IRequestBodyStrategy
    {
        public bool CanHandle(HttpRequest httpRequest)
        {
            return httpRequest.HasJsonContentType();
        }

        public async Task<JToken> ReadBodyAsJson(HttpRequest httpRequest)
        {
            var body = await httpRequest.ReadBodyStream();

            if (string.IsNullOrWhiteSpace(body))
            {
                return new JObject();
            }

            return JToken.Parse(body);
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Request/RequestBodyFactory.cs
================================================
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;

namespace Mockaco
{
    internal class RequestBodyFactory : IRequestBodyFactory
    {
        private readonly IEnumerable<IRequestBodyStrategy> _strategies;

        public RequestBodyFactory(IEnumerable<IRequestBodyStrategy> strategies)
        {
            _strategies = strategies;
        }

        public async Task<JToken> ReadBodyAsJson(HttpRequest httpRequest)
        {
            if (httpRequest.Body?.CanRead == false)
            {
                return new JObject();
            }

            var selectedStrategy = _strategies.FirstOrDefault(strategy => strategy.CanHandle(httpRequest));

            if (selectedStrategy == null)
            {
                return new JObject();
            }

            return await selectedStrategy.ReadBodyAsJson(httpRequest);
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Request/RequestConditionMatcher.cs
================================================
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace Mockaco
{
    internal class RequestConditionMatcher : IRequestMatcher
    {
        private readonly ITemplateTransformer _templateTransformer;
        private readonly IFakerFactory _fakerFactory;
        private readonly IRequestBodyFactory _requestBodyFactory;
        private readonly IMockacoContext _mockacoContext;
        private readonly IGlobalVariableStorage _globalVarialeStorage;
        private readonly ILogger _logger;

        public RequestConditionMatcher(
            ITemplateTransformer templateTransformer,
            IFakerFactory fakerFactory,
            IRequestBodyFactory requestBodyFactory,
            IMockacoContext mockacoContext,
            IGlobalVariableStorage globalVariableStoreage,
            ILogger<RequestConditionMatcher> logger)
        {
            _templateTransformer = templateTransformer;
            _fakerFactory = fakerFactory;
            _requestBodyFactory = requestBodyFactory;
            _mockacoContext = mockacoContext;
            _globalVarialeStorage = globalVariableStoreage;
            _logger = logger;
        }

        public async Task<bool> IsMatch(HttpRequest httpRequest, Mock mock)
        {
            var conditionMatcherScriptContext = new ScriptContext(_fakerFactory, _requestBodyFactory, _globalVarialeStorage);
            
            await AttachRequestToScriptContext(httpRequest.HttpContext, _mockacoContext, conditionMatcherScriptContext);

            if (_mockacoContext.Errors.Any())
            {
                return false;
            }

            await conditionMatcherScriptContext.AttachRouteParameters(httpRequest, mock);
            try
            {
                var template = await _templateTransformer.Transform(mock.RawTemplate, conditionMatcherScriptContext);

                var isMatch = template.Request?.Condition ?? true;

                return isMatch;
            }
            catch (Exception ex)
            {
                _mockacoContext.Errors.Add(new Error("Request condition could not be checked", ex));
                _logger.LogError(ex, "Request condition could not be checked");
                return false;
            }
        }

        //TODO Remove redundant code
        private async Task AttachRequestToScriptContext(HttpContext httpContext, IMockacoContext mockacoContext, IScriptContext scriptContext)
        {
            try
            {
                await scriptContext.AttachRequest(httpContext.Request);
            }
            catch (Exception ex)
            {
                mockacoContext.Errors.Add(new Error("An error occurred while reading request", ex));

                _logger.LogWarning(ex, "An error occurred while reading request");

                return;
            }
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Request/RequestMethodMatcher.cs
================================================
using Microsoft.AspNetCore.Http;
using System;
using System.Threading.Tasks;

namespace Mockaco
{
    internal class RequestMethodMatcher : IRequestMatcher
    {
        public Task<bool> IsMatch(HttpRequest httpRequest, Mock mock)
        {
            if (string.IsNullOrWhiteSpace(mock?.Method))
            {
                return Task.FromResult(httpRequest.Method == HttpMethods.Get);
            }

            var isMatch = httpRequest.Method.Equals(mock.Method, StringComparison.InvariantCultureIgnoreCase);

            return Task.FromResult(isMatch);
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Request/RequestRouteMatcher.cs
================================================
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

namespace Mockaco
{
    internal class RequestRouteMatcher : IRequestMatcher
    {
        private const string DefaultRoute = "/";

        public Task<bool> IsMatch(HttpRequest httpRequest, Mock mock)
        {
            var routeMatcher = new RouteMatcher();

            if (string.IsNullOrWhiteSpace(mock?.Route))
            {
                return Task.FromResult(routeMatcher.IsMatch(DefaultRoute, httpRequest.Path));
            }

            return Task.FromResult(routeMatcher.IsMatch(mock.Route, httpRequest.Path));
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Request/XmlRequestBodyStrategy.cs
================================================
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;
using System.Xml;

namespace Mockaco
{
    internal class XmlRequestBodyStrategy : IRequestBodyStrategy
    {
        public bool CanHandle(HttpRequest httpRequest)
        {
            return httpRequest.HasXmlContentType();
        }

        public async Task<JToken> ReadBodyAsJson(HttpRequest httpRequest)
        {
            var body = await httpRequest.ReadBodyStream();

            if (string.IsNullOrWhiteSpace(body))
            {
                return new JObject();
            }

            var xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(body);

            var json = JsonConvert.SerializeXmlNode(xmlDocument);

            return JToken.Parse(json);
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Response/BinaryResponseBodyStrategy.cs
================================================
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Mockaco
{
    internal class BinaryResponseBodyStrategy : IResponseBodyStrategy
    {
        private readonly IHttpClientFactory _httpClientFactory;

        public BinaryResponseBodyStrategy(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }

        public bool CanHandle(ResponseTemplate responseTemplate)
        {
            responseTemplate.Headers.TryGetValue(HttpHeaders.ContentType, out var contentType);

            return contentType == HttpContentTypes.ApplicationOctetStream || !string.IsNullOrEmpty(responseTemplate.File);
        }

        public async Task<byte[]> GetResponseBodyBytesFromTemplate(ResponseTemplate responseTemplate)
        {
            if (string.IsNullOrEmpty(responseTemplate.File) && string.IsNullOrEmpty(responseTemplate.Body?.ToString()))
            {
                return default;
            }

            if (string.IsNullOrEmpty(responseTemplate.File))
            {
                return Encoding.UTF8.GetBytes(responseTemplate.Body.ToString());
            }

            if (string.IsNullOrEmpty(responseTemplate.Body?.ToString()))
            {
                return await GetFileBytes(responseTemplate.File);
            }

            throw new InvalidOperationException("Both attributes \"body\" and \"file\" are set in the same response template.");
        }

        private async Task<byte[]> GetFileBytes(string path)
        {
            if (path.IsRemoteAbsolutePath())
            {
                var httpClient = _httpClientFactory.CreateClient();

                var response = await httpClient.GetAsync(path);

                return await response.Content.ReadAsByteArrayAsync();
            }
            else
            {
                return await File.ReadAllBytesAsync(path);
            }
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Response/DefaultResponseBodyStrategy.cs
================================================
namespace Mockaco
{
    internal class DefaultResponseBodyStrategy : StringResponseBodyStrategy
    {
        public override bool CanHandle(ResponseTemplate responseTemplate)
        {
            return true;
        }

        public override string GetResponseBodyStringFromTemplate(ResponseTemplate responseTemplate)
        {
            return responseTemplate.Body?.ToString();
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Response/IResponseBodyFactory.cs
================================================
using System.Threading.Tasks;

namespace Mockaco
{
    internal interface IResponseBodyFactory
    {
        Task<byte[]> GetResponseBodyBytesFromTemplate(ResponseTemplate responseTemplate);
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Response/IResponseBodyStrategy.cs
================================================
using System.Threading.Tasks;

namespace Mockaco
{
    internal interface IResponseBodyStrategy
    {
        bool CanHandle(ResponseTemplate responseTemplate);

        Task<byte[]> GetResponseBodyBytesFromTemplate(ResponseTemplate responseTemplate);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Response/JsonResponseBodyStrategy.cs
================================================
using Newtonsoft.Json;

namespace Mockaco
{
    internal class JsonResponseBodyStrategy : StringResponseBodyStrategy
    {
        public override bool CanHandle(ResponseTemplate responseTemplate)
        {
            responseTemplate.Headers.TryGetValue(HttpHeaders.ContentType, out var contentType);

            return contentType == null || contentType == HttpContentTypes.ApplicationJson;
        }

        public override string GetResponseBodyStringFromTemplate(ResponseTemplate responseTemplate)
        {
            var formatting = responseTemplate.Indented.GetValueOrDefault(true) ? Formatting.Indented : default;

            return responseTemplate.Body?.ToString(formatting);
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Response/ResponseBodyFactory.cs
================================================
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Mockaco
{
    internal class ResponseBodyFactory : IResponseBodyFactory
    {
        private readonly IEnumerable<IResponseBodyStrategy> _strategies;

        public ResponseBodyFactory(IEnumerable<IResponseBodyStrategy> strategies)
        {
            _strategies = strategies;
        }

        public Task<byte[]> GetResponseBodyBytesFromTemplate(ResponseTemplate responseTemplate)
        {
            if (responseTemplate == default)
            {
                return Task.FromResult<byte[]>(default);
            }

            var selectedStrategy = _strategies.FirstOrDefault(_ => _.CanHandle(responseTemplate));

            return selectedStrategy != null ? selectedStrategy.GetResponseBodyBytesFromTemplate(responseTemplate) : Task.FromResult<byte[]>(default);
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Response/StringResponseBodyStrategy.cs
================================================
using System.Text;
using System.Threading.Tasks;

namespace Mockaco
{
    internal abstract class StringResponseBodyStrategy : IResponseBodyStrategy
    {
        public abstract bool CanHandle(ResponseTemplate responseTemplate);

        public Task<byte[]> GetResponseBodyBytesFromTemplate(ResponseTemplate responseTemplate)
        {
            var responseBodyStringFromTemplate = GetResponseBodyStringFromTemplate(responseTemplate);

            return Task.FromResult(responseBodyStringFromTemplate == default ? default : Encoding.UTF8.GetBytes(responseBodyStringFromTemplate));
        }

        public abstract string GetResponseBodyStringFromTemplate(ResponseTemplate responseTemplate);
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Response/XmlResponseBodyStrategy.cs
================================================
using System;
using System.Text;
using System.Xml;

namespace Mockaco
{
    internal class XmlResponseBodyStrategy : StringResponseBodyStrategy
    {
        public override bool CanHandle(ResponseTemplate responseTemplate)
        {
            responseTemplate.Headers.TryGetValue(HttpHeaders.ContentType, out var contentType);

            return contentType.IsAnyOf(HttpContentTypes.ApplicationXml, HttpContentTypes.TextXml);
        }

        public override string GetResponseBodyStringFromTemplate(ResponseTemplate responseTemplate)
        {
            var settings = new XmlWriterSettings
            {
                Indent = responseTemplate.Indented.GetValueOrDefault(true)
            };

            var stringBuilder = new StringBuilder();
            using (var writer = XmlWriter.Create(stringBuilder, settings))
            {
                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(responseTemplate.Body?.ToString());
                xmlDocument.WriteContentTo(writer);
            }

            return stringBuilder.ToString();
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Scripting/IFakerFactory.cs
================================================
using Bogus;
using System.Collections.Generic;

namespace Mockaco
{
    public interface IFakerFactory
    {
        Faker GetDefaultFaker();

        Faker GetFaker(IEnumerable<string> acceptLanguages);     
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Scripting/IGlobalVarialeStorage.cs
================================================
namespace Mockaco
{
    public interface IGlobalVariableStorage
    {
        object this[string name] { get; set; }

        void EnableWriting();

        void DisableWriting();

        void Clear();
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Scripting/IScriptContext.cs
================================================
using Bogus;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

namespace Mockaco
{
    public interface IScriptContext
    {
        IGlobalVariableStorage Global { get; }

        Faker Faker { get; }

        ScriptContextRequest Request { get; set; }

        ScriptContextResponse Response { get; set; }

        Task AttachRequest(HttpRequest httpRequest);

        Task AttachRouteParameters(HttpRequest httpRequest, Mock route);

        Task AttachResponse(HttpResponse httpResponse, ResponseTemplate responseTemplate);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Scripting/IScriptRunnerFactory.cs
================================================
using Microsoft.CodeAnalysis.Scripting;
using System.Threading.Tasks;

namespace Mockaco
{
    internal interface IScriptRunnerFactory
    {
        ScriptRunner<TResult> CreateRunner<TContext, TResult>(string code);

        Task<TResult> Invoke<TContext, TResult>(TContext context, string code);
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Scripting/LocalizedFakerFactory.cs
================================================
using Bogus;
using Bogus.Extensions;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace Mockaco
{
    internal class LocalizedFakerFactory : IFakerFactory
    {
        private readonly ILogger<LocalizedFakerFactory> _logger;

        public LocalizedFakerFactory(ILogger<LocalizedFakerFactory> logger)
        {
            _logger = logger;
        }

        public Faker GetDefaultFaker()
        {
            var currentCultureBogusLocale = CultureInfo.DefaultThreadCurrentCulture?.ToBogusLocale();

            if (currentCultureBogusLocale != null)
            {
                return new Faker(currentCultureBogusLocale);
            }

            return new Faker();
        }

        public Faker GetFaker(IEnumerable<string> acceptLanguages)
        {
            var supportedBogusLocales = GetSupportedBogusLocales(acceptLanguages);

            var firstSupportedBogusLocale = supportedBogusLocales.FirstOrDefault();

            if (firstSupportedBogusLocale == default)
            {
                return GetDefaultFaker();
            }

            return new Faker(firstSupportedBogusLocale);
        }

        private IEnumerable<string> GetSupportedBogusLocales(IEnumerable<string> acceptLanguages)
        {
            var bogusLocales = new List<string>();

            foreach (var acceptLanguage in acceptLanguages)
            {
                try
                {
                    var cultureInfo = CultureInfo.GetCultureInfo(acceptLanguage);

                    var bogusLocale = cultureInfo.ToBogusLocale();

                    if (bogusLocale == default)
                    {
                        _logger.LogWarning("Accept-Language not supported by Bogus: {language}", acceptLanguage);
                    }

                    bogusLocales.Add(bogusLocale);
                }
                catch (CultureNotFoundException)
                {
                    _logger.LogWarning("Accept-Language not supported: {language}", acceptLanguage);
                }                
            }

            return bogusLocales;
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Scripting/ScriptContext.cs
================================================
using Bogus;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Mockaco
{
    public class ScriptContext : IScriptContext
    {
        private Uri _uri;
        private StringDictionary _queryDictionary = new StringDictionary();
        private StringDictionary _headersDictionary = new StringDictionary();
        private StringDictionary _routeDictionary = new StringDictionary();
        private JToken _bodyAsJson;
        private readonly IFakerFactory _fakerFactory;
        private readonly IRequestBodyFactory _requestBodyFactory;

        public IGlobalVariableStorage Global { get; }

        public Faker Faker { get; private set; }

        public ScriptContextRequest Request { get; set; }

        public ScriptContextResponse Response { get; set; }

        public ScriptContext(IFakerFactory fakerFactory, IRequestBodyFactory requestBodyFactory, IGlobalVariableStorage globalVarialeStorage)
        {
            _fakerFactory = fakerFactory;
            _requestBodyFactory = requestBodyFactory;
            Faker = fakerFactory?.GetDefaultFaker();
            Global = globalVarialeStorage;

            Request = new ScriptContextRequest(
                default,
                new StringDictionary(),
                new StringDictionary(),
                new StringDictionary(),
                new JObject());

            Response = new ScriptContextResponse(new StringDictionary(), new JObject());
        }

        public async Task AttachRequest(HttpRequest httpRequest)
        {
            _uri = httpRequest.GetUri();
            _queryDictionary = httpRequest.Query.ToStringDictionary(k => k.Key, v => v.Value.ToString());
            _headersDictionary = httpRequest.Headers.ToStringDictionary(k => k.Key, v => v.Value.ToString());
            _bodyAsJson = await _requestBodyFactory.ReadBodyAsJson(httpRequest);

            Faker = _fakerFactory?.GetFaker(httpRequest.GetAcceptLanguageValues());

            Request = new ScriptContextRequest(url: _uri, route: _routeDictionary, query: _queryDictionary, header: _headersDictionary, body: _bodyAsJson);
        }

        public Task AttachRouteParameters(HttpRequest httpRequest, Mock mock)
        {
            _routeDictionary = httpRequest.GetRouteData(mock)
                .ToStringDictionary(k => k.Key, v => v.Value.ToString());

            Request = new ScriptContextRequest(url: _uri, route: _routeDictionary, query: _queryDictionary, header: _headersDictionary, body: _bodyAsJson);

            return Task.CompletedTask;
        }

        public Task AttachResponse(HttpResponse httpResponse, ResponseTemplate responseTemplate)
        {
            Response = new ScriptContextResponse(httpResponse.Headers.ToStringDictionary(k => k.Key, v => v.Value.ToString()), responseTemplate?.Body);

            return Task.CompletedTask;
        }
    }
}

================================================
FILE: src/Mockaco.AspNetCore/Templating/Scripting/ScriptContextGlobalVariableStorage.cs
================================================
using System.Collections.Concurrent;

namespace Mockaco
{
    internal class ScriptContextGlobalVariableStorage : IGlobalVariableStorage
    {
        private static readonly ConcurrentDictionary<string, object> _variables = new ConcurrentDictionary<string, object>();

        private bool _canWrite;

        private readonly object _locker = new object();

        public object this[string name]
        {
            get
            {
                _variables.TryGetValue(name, out var value);

                return value;
            }
            set
            {
                if (_canWrite)
                {
                    _variables.AddOrUpdate(name, value, (name, _) => _variables[name] = value);
                }
            }
        }

        public void Clear()
        {
            _variables.Clear();
        }

        public void DisableWriting()
        {
            lock (_locker)
            {
                _canWrite = false;
            }
        }

        public void EnableWriting()
        {
            lock (_locker)
            {
                _canWrite = true;
            }
        }
    }
}


================================================
FILE: src/Mockaco.AspNetCore/Templating/Scripting/ScriptContextRequest.cs
================================================
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;

namespace Mockaco
{
    public class ScriptContextRequest
    {
        public Uri Url { get; }

        public IReadOnlyDictionary<st
Download .txt
gitextract_rnbuvyzp/

├── .dockerignore
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── 01_feature_request.yml
│   │   ├── 02_bug_report.yml
│   │   └── config.yml
│   ├── PULL_REQUEST_TEMPLATE/
│   │   └── pull_request_template.md
│   └── workflows/
│       ├── main-release.yml
│       ├── website-deploy-test.yml
│       └── website-deploy.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── Mockaco.sln
├── README.md
├── appveyor.yml
├── checkBuild.ps1
├── src/
│   ├── Mockaco/
│   │   ├── .dockerignore
│   │   ├── Docker/
│   │   │   ├── Dockerfile
│   │   │   └── README.md
│   │   ├── Extensions/
│   │   │   └── CommandLineExtensions.cs
│   │   ├── Mockaco.csproj
│   │   ├── Mocks/
│   │   │   └── hello.json
│   │   ├── Program.cs
│   │   ├── Properties/
│   │   │   ├── PublishProfiles/
│   │   │   │   └── FolderProfile.pubxml
│   │   │   └── launchSettings.json
│   │   ├── Settings/
│   │   │   ├── appsettings.Development.json
│   │   │   ├── appsettings.Docker.json
│   │   │   ├── appsettings.Production.json
│   │   │   └── appsettings.json
│   │   ├── Startup.Banner.cs
│   │   └── Startup.cs
│   └── Mockaco.AspNetCore/
│       ├── Chaos/
│       │   └── Strategies/
│       │       ├── ChaosStrategyBehavior.cs
│       │       ├── ChaosStrategyException.cs
│       │       ├── ChaosStrategyLatency.cs
│       │       ├── ChaosStrategyResult.cs
│       │       ├── ChaosStrategyTimeout.cs
│       │       └── IChaosStrategy.cs
│       ├── Common/
│       │   ├── HttpContentTypes.cs
│       │   ├── HttpHeaders.cs
│       │   ├── InvalidMockException.cs
│       │   ├── RouteMatcher.cs
│       │   ├── SimpleExceptionConverter.cs
│       │   └── StringDictionary.cs
│       ├── DependencyInjection/
│       │   ├── MockacoApplicationBuilder.cs
│       │   └── MockacoServiceCollection.cs
│       ├── Extensions/
│       │   ├── EnumerableExtensions.cs
│       │   ├── HttpRequestExtensions.cs
│       │   ├── ObjectExtensions.cs
│       │   ├── StringDictionaryExtensions.cs
│       │   └── StringExtensions.cs
│       ├── HealthChecks/
│       │   └── StartupHealthCheck.cs
│       ├── IMockProvider.cs
│       ├── IMockacoContext.cs
│       ├── InternalsVisibleTo.cs
│       ├── Middlewares/
│       │   ├── CallbackMiddleware.cs
│       │   ├── ChaosMiddleware.cs
│       │   ├── ErrorHandlingMiddleware.cs
│       │   ├── RequestMatchingMiddleware.cs
│       │   ├── ResponseDelayMiddleware.cs
│       │   └── ResponseMockingMiddleware.cs
│       ├── MockProvider.cs
│       ├── Mockaco.AspNetCore.csproj
│       ├── MockacoContext.cs
│       ├── Options/
│       │   ├── ChaosOptions.cs
│       │   ├── MockacoOptions.cs
│       │   └── TemplateFileProviderOptions.cs
│       ├── Plugins/
│       │   └── PhoneNumberExtensions.cs
│       ├── PublicAPI.Shipped.txt
│       ├── PublicAPI.Unshipped.txt
│       ├── Settings/
│       │   └── VerificationRouteValueTransformer.cs
│       ├── Templating/
│       │   ├── Generating/
│       │   │   ├── Cli/
│       │   │   │   └── GeneratorRunner.cs
│       │   │   ├── GeneratedTemplate.cs
│       │   │   ├── GeneratingOptions.cs
│       │   │   ├── Providers/
│       │   │   │   ├── GeneratedTemplateProviderFactory.cs
│       │   │   │   ├── IGeneratedTemplateProvider.cs
│       │   │   │   ├── IGeneratedTemplateProviderFactory.cs
│       │   │   │   └── OpenApiTemplateProvider.cs
│       │   │   ├── ServiceCollectionExtensions.cs
│       │   │   ├── Source/
│       │   │   │   ├── HttpContentProvider.cs
│       │   │   │   ├── ISourceContentProvider.cs
│       │   │   │   ├── LocalFileContentProvider.cs
│       │   │   │   └── SourceContentProviderComposite.cs
│       │   │   ├── Store/
│       │   │   │   ├── GeneratedTemplateStore.cs
│       │   │   │   ├── IGeneratedTemplateStore.cs
│       │   │   │   └── TemplateStoreOptions.cs
│       │   │   └── TemplatesGenerator.cs
│       │   ├── ITemplateTransformer.cs
│       │   ├── Models/
│       │   │   ├── CallbackTemplate.cs
│       │   │   ├── Error.cs
│       │   │   ├── IRawTemplate.cs
│       │   │   ├── Mock.cs
│       │   │   ├── RawTemplate.cs
│       │   │   ├── RequestTemplate.cs
│       │   │   ├── ResponseTemplate.cs
│       │   │   └── Template.cs
│       │   ├── Providers/
│       │   │   ├── ITemplateProvider.cs
│       │   │   └── TemplateFileProvider.cs
│       │   ├── Request/
│       │   │   ├── FormRequestBodyStrategy.cs
│       │   │   ├── IRequestBodyFactory.cs
│       │   │   ├── IRequestBodyStrategy.cs
│       │   │   ├── IRequestMatcher.cs
│       │   │   ├── JsonRequestBodyStrategy.cs
│       │   │   ├── RequestBodyFactory.cs
│       │   │   ├── RequestConditionMatcher.cs
│       │   │   ├── RequestMethodMatcher.cs
│       │   │   ├── RequestRouteMatcher.cs
│       │   │   └── XmlRequestBodyStrategy.cs
│       │   ├── Response/
│       │   │   ├── BinaryResponseBodyStrategy.cs
│       │   │   ├── DefaultResponseBodyStrategy.cs
│       │   │   ├── IResponseBodyFactory.cs
│       │   │   ├── IResponseBodyStrategy.cs
│       │   │   ├── JsonResponseBodyStrategy.cs
│       │   │   ├── ResponseBodyFactory.cs
│       │   │   ├── StringResponseBodyStrategy.cs
│       │   │   └── XmlResponseBodyStrategy.cs
│       │   ├── Scripting/
│       │   │   ├── IFakerFactory.cs
│       │   │   ├── IGlobalVarialeStorage.cs
│       │   │   ├── IScriptContext.cs
│       │   │   ├── IScriptRunnerFactory.cs
│       │   │   ├── LocalizedFakerFactory.cs
│       │   │   ├── ScriptContext.cs
│       │   │   ├── ScriptContextGlobalVariableStorage.cs
│       │   │   ├── ScriptContextRequest.cs
│       │   │   ├── ScriptContextResponse.cs
│       │   │   └── ScriptRunnerFactory.cs
│       │   ├── T4/
│       │   │   ├── TemplateSegment.cs
│       │   │   └── Tokeniser.cs
│       │   └── TemplateTransformer.cs
│       ├── Verifyer/
│       │   └── VerifyerExtensions.cs
│       └── WarmUps/
│           └── MockProviderWarmUp.cs
├── test/
│   ├── Mockaco.AspNetCore.Tests/
│   │   ├── Common/
│   │   │   └── StringDictionaryTest.cs
│   │   ├── Extensions/
│   │   │   ├── EnumerableExtensionTests.cs
│   │   │   └── StringExtensionsTests.cs
│   │   ├── Middlewares/
│   │   │   ├── CallbackMiddlewareTest.cs
│   │   │   ├── ErrorHandlingMiddlewareTest.cs
│   │   │   ├── RequestMatchingMiddlewareTest.cs
│   │   │   ├── ResponseDelayMiddlewareTest.cs
│   │   │   └── ResponseMockingMiddlewareTest.cs
│   │   ├── Mockaco.AspNetCore.Tests.csproj
│   │   ├── Templating/
│   │   │   ├── Request/
│   │   │   │   ├── JsonRequestBodyStrategyTest.cs
│   │   │   │   └── RequestConditionMatcherTest.cs
│   │   │   ├── Response/
│   │   │   │   ├── BinaryResponseBodyStrategyTest.cs
│   │   │   │   ├── DefaultResponseBodyStrategyTest.cs
│   │   │   │   ├── JsonResponseBodyStrategyTest.cs
│   │   │   │   ├── ResponseBodyFactoryTest.cs
│   │   │   │   └── XmlResponseBodyStrategyTest.cs
│   │   │   ├── Scripting/
│   │   │   │   ├── LocalizedFakerFactoryTest.cs
│   │   │   │   └── ScriptRunnerFactoryTest.cs
│   │   │   ├── TemplateTransformerTest.cs
│   │   │   ├── Transforms_Plain_Json_Template.json
│   │   │   └── Transforms_Scripted_Json_Template.json
│   │   ├── TextFileDataAttribute.cs
│   │   └── Usings.cs
│   └── _postman/
│       └── Mockaco.postman_collection.json
└── website/
    ├── .gitignore
    ├── README.md
    ├── babel.config.js
    ├── blog/
    │   └── authors.yml
    ├── docs/
    │   ├── chaos/
    │   │   └── index.md
    │   ├── configuration/
    │   │   ├── _category_.json
    │   │   └── index.md
    │   ├── generator/
    │   │   ├── _category_.json
    │   │   └── index.md
    │   ├── guides/
    │   │   ├── _category_.json
    │   │   ├── mocking-raw.md
    │   │   ├── mocking-stateful.md
    │   │   └── mocking-xml.md
    │   ├── health-checks/
    │   │   ├── _category_.json
    │   │   └── index.md
    │   ├── quick-start/
    │   │   ├── _category_.json
    │   │   ├── create-mock.md
    │   │   ├── install-run.md
    │   │   └── test-mock.md
    │   ├── reference-scripting/
    │   │   ├── _category_.json
    │   │   ├── faker.md
    │   │   ├── global.md
    │   │   ├── index.md
    │   │   ├── request.md
    │   │   └── response.md
    │   ├── reference-template/
    │   │   ├── _category_.json
    │   │   ├── callback/
    │   │   │   ├── _category_.json
    │   │   │   ├── body-attribute.md
    │   │   │   ├── delay-attribute.md
    │   │   │   ├── headers-attribute.md
    │   │   │   ├── method-attribute.md
    │   │   │   ├── timeout-attribute.md
    │   │   │   └── url-attribute.md
    │   │   ├── request/
    │   │   │   ├── _category_.json
    │   │   │   ├── condition-attribute.md
    │   │   │   ├── method-attribute.md
    │   │   │   └── route-attribute.md
    │   │   └── response/
    │   │       ├── _category_.json
    │   │       ├── body-attribute.md
    │   │       ├── delay-attribute.md
    │   │       ├── file-attribute.md
    │   │       ├── headers-attribute.md
    │   │       ├── indented-attribute.md
    │   │       └── status-attribute.md
    │   ├── request-matching/
    │   │   ├── _category_.json
    │   │   └── index.md
    │   └── verification/
    │       ├── _category_.json
    │       └── index.md
    ├── docusaurus.config.js
    ├── package.json
    ├── sidebars.js
    ├── src/
    │   ├── components/
    │   │   └── HomepageFeatures/
    │   │       ├── index.js
    │   │       └── styles.module.css
    │   ├── css/
    │   │   └── custom.css
    │   └── pages/
    │       ├── index.js
    │       ├── index.module.css
    │       ├── videos.js
    │       └── videos.module.css
    └── static/
        └── .nojekyll
Download .txt
SYMBOL INDEX (443 symbols across 121 files)

FILE: src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyBehavior.cs
  class ChaosStrategyBehavior (line 7) | internal class ChaosStrategyBehavior : IChaosStrategy
    method Response (line 9) | public Task Response(HttpResponse httpResponse)

FILE: src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyException.cs
  class ChaosStrategyException (line 7) | internal class ChaosStrategyException : IChaosStrategy
    method Response (line 9) | public Task Response(HttpResponse httpResponse)

FILE: src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyLatency.cs
  class ChaosStrategyLatency (line 7) | internal class ChaosStrategyLatency : IChaosStrategy
    method ChaosStrategyLatency (line 12) | public ChaosStrategyLatency(ILogger<ChaosStrategyLatency> logger, IOpt...
    method Response (line 17) | public Task Response(HttpResponse httpResponse)

FILE: src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyResult.cs
  class ChaosStrategyResult (line 7) | internal class ChaosStrategyResult : IChaosStrategy
    method Response (line 9) | public Task Response(HttpResponse httpResponse)

FILE: src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyTimeout.cs
  class ChaosStrategyTimeout (line 8) | internal class ChaosStrategyTimeout : IChaosStrategy
    method ChaosStrategyTimeout (line 12) | public ChaosStrategyTimeout(IOptions<ChaosOptions> options)
    method Response (line 17) | public async Task Response(HttpResponse httpResponse)

FILE: src/Mockaco.AspNetCore/Chaos/Strategies/IChaosStrategy.cs
  type IChaosStrategy (line 5) | internal interface IChaosStrategy
    method Response (line 7) | Task Response(HttpResponse httpResponse);

FILE: src/Mockaco.AspNetCore/Common/HttpContentTypes.cs
  class HttpContentTypes (line 3) | internal static class HttpContentTypes

FILE: src/Mockaco.AspNetCore/Common/HttpHeaders.cs
  class HttpHeaders (line 3) | internal static class HttpHeaders

FILE: src/Mockaco.AspNetCore/Common/InvalidMockException.cs
  class InvalidMockException (line 10) | internal class InvalidMockException : Exception
    method InvalidMockException (line 12) | public InvalidMockException() : base() { }
    method InvalidMockException (line 14) | public InvalidMockException(string message) : base(message)
    method InvalidMockException (line 18) | public InvalidMockException(string message, Exception innerException) ...
    method InvalidMockException (line 22) | protected InvalidMockException(SerializationInfo info, StreamingContex...

FILE: src/Mockaco.AspNetCore/Common/RouteMatcher.cs
  class RouteMatcher (line 6) | internal class RouteMatcher
    method Match (line 8) | public RouteValueDictionary Match(string routeTemplate, string request...
    method IsMatch (line 24) | public bool IsMatch(string routeTemplate, string requestPath)
    method GetDefaults (line 29) | private RouteValueDictionary GetDefaults(RouteTemplate parsedTemplate)

FILE: src/Mockaco.AspNetCore/Common/SimpleExceptionConverter.cs
  class SimpleExceptionConverter (line 7) | internal class SimpleExceptionConverter : JsonConverter
    method CanConvert (line 9) | public override bool CanConvert(Type objectType)
    method ReadJson (line 14) | public override object ReadJson(JsonReader reader, Type objectType, ob...
    method WriteJson (line 19) | public override void WriteJson(JsonWriter writer, object value, JsonSe...

FILE: src/Mockaco.AspNetCore/Common/StringDictionary.cs
  class StringDictionary (line 5) | public class StringDictionary : Dictionary<string, string>, IReadOnlyDic...
    method Add (line 24) | public new void Add(string key, string value)
    method Replace (line 29) | public void Replace(string key, string value)

FILE: src/Mockaco.AspNetCore/DependencyInjection/MockacoApplicationBuilder.cs
  class MockacoApplicationBuilder (line 11) | public static class MockacoApplicationBuilder
    method UseMockaco (line 13) | public static IApplicationBuilder UseMockaco(this IApplicationBuilder ...
    method UseMockaco (line 48) | public static IApplicationBuilder UseMockaco(this IApplicationBuilder ...

FILE: src/Mockaco.AspNetCore/DependencyInjection/MockacoServiceCollection.cs
  class MockacoServiceCollection (line 11) | public static class MockacoServiceCollection
    method AddMockaco (line 13) | public static IServiceCollection AddMockaco(this IServiceCollection se...
    method AddMockaco (line 16) | public static IServiceCollection AddMockaco(this IServiceCollection se...
    method AddMockaco (line 26) | public static IServiceCollection AddMockaco(this IServiceCollection se...
    method AddConfiguration (line 31) | private static IServiceCollection AddConfiguration(this IServiceCollec...
    method AddCommonServices (line 38) | private static IServiceCollection AddCommonServices(this IServiceColle...
    method AddInternalServices (line 55) | private static IServiceCollection AddInternalServices(this IServiceCol...
    method AddChaosServices (line 89) | private static IServiceCollection AddChaosServices(this IServiceCollec...

FILE: src/Mockaco.AspNetCore/Extensions/EnumerableExtensions.cs
  class EnumerableExtensions (line 5) | internal static class EnumerableExtensions
    method AllAsync (line 7) | public static async Task<bool> AllAsync<TSource>(this IEnumerable<TSou...
    method AllAsync (line 25) | public static async Task<bool> AllAsync<TSource>(this IEnumerable<Task...
    method Random (line 43) | public static T Random<T>(this IEnumerable<T> enumerable) {

FILE: src/Mockaco.AspNetCore/Extensions/HttpRequestExtensions.cs
  class HttpRequestExtensions (line 39) | internal static class HttpRequestExtensions
    method GetUri (line 48) | public static Uri GetUri(this HttpRequest request)
    method GetRouteData (line 81) | public static Routing.RouteValueDictionary GetRouteData(this HttpReque...
    method HasXmlContentType (line 88) | public static bool HasXmlContentType(this HttpRequest request)
    method ReadBodyStream (line 96) | public static async Task<string> ReadBodyStream(this HttpRequest httpR...
    method GetAcceptLanguageValues (line 113) | public static IEnumerable<string> GetAcceptLanguageValues(this HttpReq...
    method GetEncodingFromContentType (line 125) | private static Encoding GetEncodingFromContentType(string contentType)

FILE: src/Mockaco.AspNetCore/Extensions/ObjectExtensions.cs
  class ObjectExtensions (line 9) | internal static class ObjectExtensions
    method ToJson (line 21) | public static string ToJson<T>(this T param)
    method IsAnyOf (line 39) | public static bool IsAnyOf<T>(this T item, params T[] possibleItems)

FILE: src/Mockaco.AspNetCore/Extensions/StringDictionaryExtensions.cs
  class StringDictionaryExtensions (line 5) | internal static class StringDictionaryExtensions
    method ToStringDictionary (line 7) | public static StringDictionary ToStringDictionary<TSource>(

FILE: src/Mockaco.AspNetCore/Extensions/StringExtensions.cs
  class StringExtensions (line 5) | internal static class StringExtensions
    method ToMD5Hash (line 7) | public static string ToMD5Hash(this string input)
    method IsRemoteAbsolutePath (line 23) | public static bool IsRemoteAbsolutePath(this string input)

FILE: src/Mockaco.AspNetCore/HealthChecks/StartupHealthCheck.cs
  class StartupHealthCheck (line 5) | public class StartupHealthCheck : IHealthCheck
    method CheckHealthAsync (line 15) | public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext con...

FILE: src/Mockaco.AspNetCore/IMockProvider.cs
  type IMockProvider (line 6) | internal interface IMockProvider
    method GetMocks (line 8) | List<Mock> GetMocks();
    method GetErrors (line 10) | IEnumerable<(string TemplateName, string ErrorMessage)> GetErrors();
    method WarmUp (line 12) | Task WarmUp();

FILE: src/Mockaco.AspNetCore/IMockacoContext.cs
  type IMockacoContext (line 5) | internal interface IMockacoContext

FILE: src/Mockaco.AspNetCore/Middlewares/CallbackMiddleware.cs
  class CallbackMiddleware (line 17) | internal class CallbackMiddleware
    method CallbackMiddleware (line 22) | public CallbackMiddleware(RequestDelegate next, ILogger<CallbackMiddle...
    method Invoke (line 28) | public Task Invoke(
    method PerformCallbacks (line 51) | private async Task PerformCallbacks(
    method PerformCallback (line 79) | private async Task PerformCallback(HttpContext httpContext, CallbackTe...
    method PrepareHttpRequest (line 103) | private static HttpRequestMessage PrepareHttpRequest(CallbackTemplate ...
    method PrepareHeaders (line 121) | private static void PrepareHeaders(CallbackTemplate callBackTemplate, ...
    method PrepareHttpClient (line 142) | private static HttpClient PrepareHttpClient(HttpContext httpContext, C...
    method DelayRequest (line 152) | private async Task DelayRequest(CallbackTemplate callbackTemplate, lon...
    method PerformRequest (line 162) | private async Task PerformRequest(HttpRequestMessage request, HttpClie...

FILE: src/Mockaco.AspNetCore/Middlewares/ChaosMiddleware.cs
  class ChaosMiddleware (line 9) | internal class ChaosMiddleware
    method ChaosMiddleware (line 19) | public ChaosMiddleware(
    method Invoke (line 31) | public async Task Invoke(HttpContext httpContext)
    method GenerateErrorList (line 59) | private List<int> GenerateErrorList(int rate)

FILE: src/Mockaco.AspNetCore/Middlewares/ErrorHandlingMiddleware.cs
  class ErrorHandlingMiddleware (line 10) | internal class ErrorHandlingMiddleware
    method ErrorHandlingMiddleware (line 14) | public ErrorHandlingMiddleware(RequestDelegate next)
    method Invoke (line 19) | public async Task Invoke(
    method IncludeMockProviderErrors (line 50) | private static void IncludeMockProviderErrors(IMockacoContext mockacoC...

FILE: src/Mockaco.AspNetCore/Middlewares/RequestMatchingMiddleware.cs
  class RequestMatchingMiddleware (line 12) | internal class RequestMatchingMiddleware
    method RequestMatchingMiddleware (line 17) | public RequestMatchingMiddleware(RequestDelegate next, ILogger<Request...
    method Invoke (line 23) | public async Task Invoke(
    method AttachRequestToScriptContext (line 80) | private async Task AttachRequestToScriptContext(HttpContext httpContex...
    method LogHttpContext (line 96) | private async Task LogHttpContext(HttpContext httpContext)
    method LoadHeaders (line 114) | private static IEnumerable<object> LoadHeaders(HttpContext httpContext...

FILE: src/Mockaco.AspNetCore/Middlewares/ResponseDelayMiddleware.cs
  class ResponseDelayMiddleware (line 8) | internal class ResponseDelayMiddleware
    method ResponseDelayMiddleware (line 12) | public ResponseDelayMiddleware(RequestDelegate next)
    method Invoke (line 17) | public async Task Invoke(HttpContext httpContext, IMockacoContext mock...

FILE: src/Mockaco.AspNetCore/Middlewares/ResponseMockingMiddleware.cs
  class ResponseMockingMiddleware (line 8) | internal class ResponseMockingMiddleware
    method ResponseMockingMiddleware (line 12) | public ResponseMockingMiddleware(RequestDelegate next)
    method Invoke (line 17) | public async Task Invoke(
    method PrepareResponse (line 31) | private async Task PrepareResponse(
    method GetResponseStatusFromTemplate (line 51) | private int GetResponseStatusFromTemplate(ResponseTemplate responseTem...
    method AddHeadersFromTemplate (line 58) | private void AddHeadersFromTemplate(HttpResponse response, ResponseTem...

FILE: src/Mockaco.AspNetCore/MockProvider.cs
  class MockProvider (line 14) | internal class MockProvider : IMockProvider
    method MockProvider (line 26) | public MockProvider
    method TemplateProviderChange (line 47) | private async void TemplateProviderChange(object sender, EventArgs e)
    method GetMocks (line 53) | public List<Mock> GetMocks()
    method GetErrors (line 58) | public IEnumerable<(string TemplateName, string ErrorMessage)> GetErro...
    method WarmUp (line 63) | public async Task WarmUp()
    method CreateMock (line 127) | private static Mock CreateMock(IRawTemplate rawTemplate, RequestTempla...

FILE: src/Mockaco.AspNetCore/MockacoContext.cs
  class MockacoContext (line 5) | internal class MockacoContext : IMockacoContext
    method MockacoContext (line 15) | public MockacoContext(IScriptContext scriptContext)

FILE: src/Mockaco.AspNetCore/Options/ChaosOptions.cs
  class ChaosOptions (line 3) | public class ChaosOptions
    method ChaosOptions (line 11) | public ChaosOptions()

FILE: src/Mockaco.AspNetCore/Options/MockacoOptions.cs
  class MockacoOptions (line 5) | public class MockacoOptions
    method MockacoOptions (line 32) | public MockacoOptions()

FILE: src/Mockaco.AspNetCore/Options/TemplateFileProviderOptions.cs
  class TemplateFileProviderOptions (line 8) | public class TemplateFileProviderOptions
    method TemplateFileProviderOptions (line 12) | public TemplateFileProviderOptions()

FILE: src/Mockaco.AspNetCore/Plugins/PhoneNumberExtensions.cs
  class PhoneNumberExtensions (line 6) | public static class PhoneNumberExtensions
    method BrazilianPhoneNumber (line 8) | public static string BrazilianPhoneNumber(this PhoneNumbers phoneNumbers)

FILE: src/Mockaco.AspNetCore/Settings/VerificationRouteValueTransformer.cs
  class VerificationRouteValueTransformer (line 8) | internal class VerificationRouteValueTransformer : DynamicRouteValueTran...
    method TransformAsync (line 10) | public override ValueTask<RouteValueDictionary> TransformAsync(HttpCon...

FILE: src/Mockaco.AspNetCore/Templating/Generating/Cli/GeneratorRunner.cs
  class GeneratorRunner (line 9) | internal class GeneratorRunner
    method GeneratorRunner (line 13) | public GeneratorRunner(IServiceProvider serviceProvider)
    method ExecuteAsync (line 18) | public async Task<int> ExecuteAsync(GeneratingOptions options, IConsol...

FILE: src/Mockaco.AspNetCore/Templating/Generating/GeneratedTemplate.cs
  class GeneratedTemplate (line 3) | internal class GeneratedTemplate : Template

FILE: src/Mockaco.AspNetCore/Templating/Generating/GeneratingOptions.cs
  class GeneratingOptions (line 6) | internal class GeneratingOptions

FILE: src/Mockaco.AspNetCore/Templating/Generating/Providers/GeneratedTemplateProviderFactory.cs
  class GeneratedTemplateProviderFactory (line 7) | internal class GeneratedTemplateProviderFactory : IGeneratedTemplateProv...
    method GeneratedTemplateProviderFactory (line 16) | public GeneratedTemplateProviderFactory(IServiceProvider serviceProvider)
    method Create (line 21) | public IGeneratedTemplateProvider Create(string providerType)

FILE: src/Mockaco.AspNetCore/Templating/Generating/Providers/IGeneratedTemplateProvider.cs
  type IGeneratedTemplateProvider (line 8) | internal interface IGeneratedTemplateProvider
    method GetTemplatesAsync (line 10) | Task<IEnumerable<GeneratedTemplate>> GetTemplatesAsync(Stream sourceSt...

FILE: src/Mockaco.AspNetCore/Templating/Generating/Providers/IGeneratedTemplateProviderFactory.cs
  type IGeneratedTemplateProviderFactory (line 3) | internal interface IGeneratedTemplateProviderFactory
    method Create (line 5) | IGeneratedTemplateProvider Create(string providerType);

FILE: src/Mockaco.AspNetCore/Templating/Generating/Providers/OpenApiTemplateProvider.cs
  class OpenApiTemplateProvider (line 15) | internal class OpenApiTemplateProvider : IGeneratedTemplateProvider
    method OpenApiTemplateProvider (line 19) | public OpenApiTemplateProvider(ILogger<OpenApiTemplateProvider> logger)
    method GetTemplatesAsync (line 24) | public Task<IEnumerable<GeneratedTemplate>> GetTemplatesAsync(Stream s...
    method BuildTemplates (line 40) | private IEnumerable<GeneratedTemplate> BuildTemplates(OpenApiDocument ...
    method SetTemplateName (line 58) | private void SetTemplateName(GeneratedTemplate template, KeyValuePair<...
    method BuildResponse (line 70) | private ResponseTemplate BuildResponse(KeyValuePair<OperationType,Open...
    method BuildRequest (line 94) | private RequestTemplate BuildRequest(KeyValuePair<string,OpenApiPathIt...
    method LogDiagnostics (line 103) | private void LogDiagnostics(OpenApiDiagnostic diagnostic)

FILE: src/Mockaco.AspNetCore/Templating/Generating/ServiceCollectionExtensions.cs
  class ServiceCollectionExtensions (line 11) | internal static class ServiceCollectionExtensions
    method AddTemplatesGenerating (line 13) | public static IServiceCollection AddTemplatesGenerating(this IServiceC...

FILE: src/Mockaco.AspNetCore/Templating/Generating/Source/HttpContentProvider.cs
  class HttpContentProvider (line 9) | internal class HttpContentProvider : ISourceContentProvider
    method GetStreamAsync (line 11) | public async Task<Stream> GetStreamAsync(Uri sourceUri, CancellationTo...

FILE: src/Mockaco.AspNetCore/Templating/Generating/Source/ISourceContentProvider.cs
  type ISourceContentProvider (line 8) | internal interface ISourceContentProvider
    method GetStreamAsync (line 10) | Task<Stream> GetStreamAsync(Uri sourceUri, CancellationToken cancellat...

FILE: src/Mockaco.AspNetCore/Templating/Generating/Source/LocalFileContentProvider.cs
  class LocalFileContentProvider (line 8) | internal class LocalFileContentProvider : ISourceContentProvider
    method GetStreamAsync (line 10) | public Task<Stream> GetStreamAsync(Uri sourceUri, CancellationToken ca...

FILE: src/Mockaco.AspNetCore/Templating/Generating/Source/SourceContentProviderComposite.cs
  class SourceContentProviderComposite (line 10) | internal class SourceContentProviderComposite : ISourceContentProvider
    method SourceContentProviderComposite (line 15) | public SourceContentProviderComposite(IServiceProvider serviceProvider)
    method RegisterDefaultProviders (line 21) | private void RegisterDefaultProviders()
    method Create (line 27) | private ISourceContentProvider Create(Uri sourceUri)
    method Register (line 43) | public void Register(Predicate<Uri> canHandle, Type type)
    method GetStreamAsync (line 48) | public Task<Stream> GetStreamAsync(Uri sourceUri, CancellationToken ca...

FILE: src/Mockaco.AspNetCore/Templating/Generating/Store/GeneratedTemplateStore.cs
  class GeneratedTemplateStore (line 11) | internal class GeneratedTemplateStore : IGeneratedTemplateStore
    method GeneratedTemplateStore (line 18) | public GeneratedTemplateStore(IOptions<TemplateStoreOptions> options, ...
    method SaveAsync (line 26) | public async Task SaveAsync(GeneratedTemplate template, CancellationTo...
    method GetTemplateContent (line 35) | private byte[] GetTemplateContent(GeneratedTemplate template)
    method SaveAsync (line 45) | public async Task SaveAsync(IEnumerable<GeneratedTemplate> templates, ...
    method GetFileName (line 55) | private string GetFileName(GeneratedTemplate template)

FILE: src/Mockaco.AspNetCore/Templating/Generating/Store/IGeneratedTemplateStore.cs
  type IGeneratedTemplateStore (line 7) | internal interface IGeneratedTemplateStore
    method SaveAsync (line 9) | Task SaveAsync(GeneratedTemplate template, CancellationToken cancellat...
    method SaveAsync (line 11) | Task SaveAsync(IEnumerable<GeneratedTemplate> templates, CancellationT...

FILE: src/Mockaco.AspNetCore/Templating/Generating/Store/TemplateStoreOptions.cs
  class TemplateStoreOptions (line 3) | internal class TemplateStoreOptions

FILE: src/Mockaco.AspNetCore/Templating/Generating/TemplatesGenerator.cs
  class TemplatesGenerator (line 9) | internal class TemplatesGenerator
    method TemplatesGenerator (line 15) | public TemplatesGenerator(ISourceContentProvider sourceContentProvider...
    method GenerateAsync (line 22) | public async Task GenerateAsync(GeneratingOptions options, Cancellatio...

FILE: src/Mockaco.AspNetCore/Templating/ITemplateTransformer.cs
  type ITemplateTransformer (line 5) | internal interface ITemplateTransformer
    method TransformAndSetVariables (line 8) | Task<Template> TransformAndSetVariables(IRawTemplate rawTemplate, IScr...
    method Transform (line 10) | Task<Template> Transform(IRawTemplate rawTemplate, IScriptContext scri...

FILE: src/Mockaco.AspNetCore/Templating/Models/CallbackTemplate.cs
  class CallbackTemplate (line 6) | internal class CallbackTemplate

FILE: src/Mockaco.AspNetCore/Templating/Models/Error.cs
  class Error (line 5) | internal class Error
    method Error (line 11) | public Error(string message)
    method Error (line 16) | public Error(Exception exception)
    method Error (line 21) | public Error(string message, Exception exception)

FILE: src/Mockaco.AspNetCore/Templating/Models/IRawTemplate.cs
  type IRawTemplate (line 3) | public interface IRawTemplate

FILE: src/Mockaco.AspNetCore/Templating/Models/Mock.cs
  class Mock (line 5) | [DebuggerDisplay("{Method} {Route} ({RawTemplate.Name})")]
    method Mock (line 16) | public Mock(string method, string route, IRawTemplate rawTemplate, boo...
    method ToString (line 24) | public override string ToString()

FILE: src/Mockaco.AspNetCore/Templating/Models/RawTemplate.cs
  class RawTemplate (line 6) | [DebuggerDisplay("{Name}")]
    method RawTemplate (line 15) | public RawTemplate(string name, string content)

FILE: src/Mockaco.AspNetCore/Templating/Models/RequestTemplate.cs
  class RequestTemplate (line 3) | internal class RequestTemplate

FILE: src/Mockaco.AspNetCore/Templating/Models/ResponseTemplate.cs
  class ResponseTemplate (line 7) | public class ResponseTemplate
    method ResponseTemplate (line 21) | public ResponseTemplate()

FILE: src/Mockaco.AspNetCore/Templating/Models/Template.cs
  class Template (line 6) | internal class Template
    method Template (line 8) | public Template()

FILE: src/Mockaco.AspNetCore/Templating/Providers/ITemplateProvider.cs
  type ITemplateProvider (line 6) | internal interface ITemplateProvider
    method GetTemplates (line 10) | IEnumerable<IRawTemplate> GetTemplates();

FILE: src/Mockaco.AspNetCore/Templating/Providers/TemplateFileProvider.cs
  class TemplateFileProvider (line 18) | internal sealed class TemplateFileProvider : ITemplateProvider, IDisposable
    method TemplateFileProvider (line 31) | public TemplateFileProvider(IOptionsMonitor<TemplateFileProviderOption...
    method SetMockRootPath (line 45) | private void SetMockRootPath(string path)
    method ResetCacheAndNotifyChange (line 76) | private void ResetCacheAndNotifyChange()
    method KeepWatchingForFileChanges (line 86) | private void KeepWatchingForFileChanges()
    method TemplateFileModified (line 100) | private void TemplateFileModified(object state)
    method GetTemplates (line 107) | public IEnumerable<IRawTemplate> GetTemplates()
    method PostEvictionCallback (line 120) | private void PostEvictionCallback(object key, object value, EvictionRe...
    method LoadTemplatesFromDirectory (line 125) | private IEnumerable<IRawTemplate> LoadTemplatesFromDirectory()
    method ShouldIgnoreFile (line 163) | private bool ShouldIgnoreFile(FileInfo file)
    method WrapWithFileExceptionHandling (line 185) | private T WrapWithFileExceptionHandling<T>(string path, Func<T> action)
    method FlushCache (line 204) | private void FlushCache()
    method Dispose (line 215) | public void Dispose()

FILE: src/Mockaco.AspNetCore/Templating/Request/FormRequestBodyStrategy.cs
  class FormRequestBodyStrategy (line 8) | internal class FormRequestBodyStrategy : IRequestBodyStrategy
    method CanHandle (line 10) | public bool CanHandle(HttpRequest httpRequest)
    method ReadBodyAsJson (line 15) | public Task<JToken> ReadBodyAsJson(HttpRequest httpRequest)

FILE: src/Mockaco.AspNetCore/Templating/Request/IRequestBodyFactory.cs
  type IRequestBodyFactory (line 7) | public interface IRequestBodyFactory
    method ReadBodyAsJson (line 9) | Task<JToken> ReadBodyAsJson(HttpRequest httpRequest);

FILE: src/Mockaco.AspNetCore/Templating/Request/IRequestBodyStrategy.cs
  type IRequestBodyStrategy (line 7) | internal interface IRequestBodyStrategy
    method CanHandle (line 9) | bool CanHandle(HttpRequest httpRequest);
    method ReadBodyAsJson (line 10) | Task<JToken> ReadBodyAsJson(HttpRequest httpRequest);

FILE: src/Mockaco.AspNetCore/Templating/Request/IRequestMatcher.cs
  type IRequestMatcher (line 6) | internal interface IRequestMatcher
    method IsMatch (line 8) | Task<bool> IsMatch(HttpRequest httpRequest, Mock mock);

FILE: src/Mockaco.AspNetCore/Templating/Request/JsonRequestBodyStrategy.cs
  class JsonRequestBodyStrategy (line 9) | internal class JsonRequestBodyStrategy: IRequestBodyStrategy
    method CanHandle (line 11) | public bool CanHandle(HttpRequest httpRequest)
    method ReadBodyAsJson (line 16) | public async Task<JToken> ReadBodyAsJson(HttpRequest httpRequest)

FILE: src/Mockaco.AspNetCore/Templating/Request/RequestBodyFactory.cs
  class RequestBodyFactory (line 9) | internal class RequestBodyFactory : IRequestBodyFactory
    method RequestBodyFactory (line 13) | public RequestBodyFactory(IEnumerable<IRequestBodyStrategy> strategies)
    method ReadBodyAsJson (line 18) | public async Task<JToken> ReadBodyAsJson(HttpRequest httpRequest)

FILE: src/Mockaco.AspNetCore/Templating/Request/RequestConditionMatcher.cs
  class RequestConditionMatcher (line 7) | internal class RequestConditionMatcher : IRequestMatcher
    method RequestConditionMatcher (line 16) | public RequestConditionMatcher(
    method IsMatch (line 32) | public async Task<bool> IsMatch(HttpRequest httpRequest, Mock mock)
    method AttachRequestToScriptContext (line 61) | private async Task AttachRequestToScriptContext(HttpContext httpContex...

FILE: src/Mockaco.AspNetCore/Templating/Request/RequestMethodMatcher.cs
  class RequestMethodMatcher (line 7) | internal class RequestMethodMatcher : IRequestMatcher
    method IsMatch (line 9) | public Task<bool> IsMatch(HttpRequest httpRequest, Mock mock)

FILE: src/Mockaco.AspNetCore/Templating/Request/RequestRouteMatcher.cs
  class RequestRouteMatcher (line 6) | internal class RequestRouteMatcher : IRequestMatcher
    method IsMatch (line 10) | public Task<bool> IsMatch(HttpRequest httpRequest, Mock mock)

FILE: src/Mockaco.AspNetCore/Templating/Request/XmlRequestBodyStrategy.cs
  class XmlRequestBodyStrategy (line 9) | internal class XmlRequestBodyStrategy : IRequestBodyStrategy
    method CanHandle (line 11) | public bool CanHandle(HttpRequest httpRequest)
    method ReadBodyAsJson (line 16) | public async Task<JToken> ReadBodyAsJson(HttpRequest httpRequest)

FILE: src/Mockaco.AspNetCore/Templating/Response/BinaryResponseBodyStrategy.cs
  class BinaryResponseBodyStrategy (line 9) | internal class BinaryResponseBodyStrategy : IResponseBodyStrategy
    method BinaryResponseBodyStrategy (line 13) | public BinaryResponseBodyStrategy(IHttpClientFactory httpClientFactory)
    method CanHandle (line 18) | public bool CanHandle(ResponseTemplate responseTemplate)
    method GetResponseBodyBytesFromTemplate (line 25) | public async Task<byte[]> GetResponseBodyBytesFromTemplate(ResponseTem...
    method GetFileBytes (line 45) | private async Task<byte[]> GetFileBytes(string path)

FILE: src/Mockaco.AspNetCore/Templating/Response/DefaultResponseBodyStrategy.cs
  class DefaultResponseBodyStrategy (line 3) | internal class DefaultResponseBodyStrategy : StringResponseBodyStrategy
    method CanHandle (line 5) | public override bool CanHandle(ResponseTemplate responseTemplate)
    method GetResponseBodyStringFromTemplate (line 10) | public override string GetResponseBodyStringFromTemplate(ResponseTempl...

FILE: src/Mockaco.AspNetCore/Templating/Response/IResponseBodyFactory.cs
  type IResponseBodyFactory (line 5) | internal interface IResponseBodyFactory
    method GetResponseBodyBytesFromTemplate (line 7) | Task<byte[]> GetResponseBodyBytesFromTemplate(ResponseTemplate respons...

FILE: src/Mockaco.AspNetCore/Templating/Response/IResponseBodyStrategy.cs
  type IResponseBodyStrategy (line 5) | internal interface IResponseBodyStrategy
    method CanHandle (line 7) | bool CanHandle(ResponseTemplate responseTemplate);
    method GetResponseBodyBytesFromTemplate (line 9) | Task<byte[]> GetResponseBodyBytesFromTemplate(ResponseTemplate respons...

FILE: src/Mockaco.AspNetCore/Templating/Response/JsonResponseBodyStrategy.cs
  class JsonResponseBodyStrategy (line 5) | internal class JsonResponseBodyStrategy : StringResponseBodyStrategy
    method CanHandle (line 7) | public override bool CanHandle(ResponseTemplate responseTemplate)
    method GetResponseBodyStringFromTemplate (line 14) | public override string GetResponseBodyStringFromTemplate(ResponseTempl...

FILE: src/Mockaco.AspNetCore/Templating/Response/ResponseBodyFactory.cs
  class ResponseBodyFactory (line 7) | internal class ResponseBodyFactory : IResponseBodyFactory
    method ResponseBodyFactory (line 11) | public ResponseBodyFactory(IEnumerable<IResponseBodyStrategy> strategies)
    method GetResponseBodyBytesFromTemplate (line 16) | public Task<byte[]> GetResponseBodyBytesFromTemplate(ResponseTemplate ...

FILE: src/Mockaco.AspNetCore/Templating/Response/StringResponseBodyStrategy.cs
  class StringResponseBodyStrategy (line 6) | internal abstract class StringResponseBodyStrategy : IResponseBodyStrategy
    method CanHandle (line 8) | public abstract bool CanHandle(ResponseTemplate responseTemplate);
    method GetResponseBodyBytesFromTemplate (line 10) | public Task<byte[]> GetResponseBodyBytesFromTemplate(ResponseTemplate ...
    method GetResponseBodyStringFromTemplate (line 17) | public abstract string GetResponseBodyStringFromTemplate(ResponseTempl...

FILE: src/Mockaco.AspNetCore/Templating/Response/XmlResponseBodyStrategy.cs
  class XmlResponseBodyStrategy (line 7) | internal class XmlResponseBodyStrategy : StringResponseBodyStrategy
    method CanHandle (line 9) | public override bool CanHandle(ResponseTemplate responseTemplate)
    method GetResponseBodyStringFromTemplate (line 16) | public override string GetResponseBodyStringFromTemplate(ResponseTempl...

FILE: src/Mockaco.AspNetCore/Templating/Scripting/IFakerFactory.cs
  type IFakerFactory (line 6) | public interface IFakerFactory
    method GetDefaultFaker (line 8) | Faker GetDefaultFaker();
    method GetFaker (line 10) | Faker GetFaker(IEnumerable<string> acceptLanguages);

FILE: src/Mockaco.AspNetCore/Templating/Scripting/IGlobalVarialeStorage.cs
  type IGlobalVariableStorage (line 3) | public interface IGlobalVariableStorage
    method EnableWriting (line 7) | void EnableWriting();
    method DisableWriting (line 9) | void DisableWriting();
    method Clear (line 11) | void Clear();

FILE: src/Mockaco.AspNetCore/Templating/Scripting/IScriptContext.cs
  type IScriptContext (line 7) | public interface IScriptContext
    method AttachRequest (line 17) | Task AttachRequest(HttpRequest httpRequest);
    method AttachRouteParameters (line 19) | Task AttachRouteParameters(HttpRequest httpRequest, Mock route);
    method AttachResponse (line 21) | Task AttachResponse(HttpResponse httpResponse, ResponseTemplate respon...

FILE: src/Mockaco.AspNetCore/Templating/Scripting/IScriptRunnerFactory.cs
  type IScriptRunnerFactory (line 6) | internal interface IScriptRunnerFactory
    method CreateRunner (line 8) | ScriptRunner<TResult> CreateRunner<TContext, TResult>(string code);
    method Invoke (line 10) | Task<TResult> Invoke<TContext, TResult>(TContext context, string code);

FILE: src/Mockaco.AspNetCore/Templating/Scripting/LocalizedFakerFactory.cs
  class LocalizedFakerFactory (line 10) | internal class LocalizedFakerFactory : IFakerFactory
    method LocalizedFakerFactory (line 14) | public LocalizedFakerFactory(ILogger<LocalizedFakerFactory> logger)
    method GetDefaultFaker (line 19) | public Faker GetDefaultFaker()
    method GetFaker (line 31) | public Faker GetFaker(IEnumerable<string> acceptLanguages)
    method GetSupportedBogusLocales (line 45) | private IEnumerable<string> GetSupportedBogusLocales(IEnumerable<strin...

FILE: src/Mockaco.AspNetCore/Templating/Scripting/ScriptContext.cs
  class ScriptContext (line 10) | public class ScriptContext : IScriptContext
    method ScriptContext (line 28) | public ScriptContext(IFakerFactory fakerFactory, IRequestBodyFactory r...
    method AttachRequest (line 45) | public async Task AttachRequest(HttpRequest httpRequest)
    method AttachRouteParameters (line 57) | public Task AttachRouteParameters(HttpRequest httpRequest, Mock mock)
    method AttachResponse (line 67) | public Task AttachResponse(HttpResponse httpResponse, ResponseTemplate...

FILE: src/Mockaco.AspNetCore/Templating/Scripting/ScriptContextGlobalVariableStorage.cs
  class ScriptContextGlobalVariableStorage (line 5) | internal class ScriptContextGlobalVariableStorage : IGlobalVariableStorage
    method Clear (line 30) | public void Clear()
    method DisableWriting (line 35) | public void DisableWriting()
    method EnableWriting (line 43) | public void EnableWriting()

FILE: src/Mockaco.AspNetCore/Templating/Scripting/ScriptContextRequest.cs
  class ScriptContextRequest (line 7) | public class ScriptContextRequest
    method ScriptContextRequest (line 19) | public ScriptContextRequest(

FILE: src/Mockaco.AspNetCore/Templating/Scripting/ScriptContextResponse.cs
  class ScriptContextResponse (line 6) | public class ScriptContextResponse
    method ScriptContextResponse (line 12) | public ScriptContextResponse(StringDictionary header, JToken body)

FILE: src/Mockaco.AspNetCore/Templating/Scripting/ScriptRunnerFactory.cs
  class ScriptRunnerFactory (line 12) | internal class ScriptRunnerFactory : IScriptRunnerFactory
    method ScriptRunnerFactory (line 19) | public ScriptRunnerFactory(ILogger<ScriptRunnerFactory> logger, IOptio...
    method Invoke (line 26) | public Task<TResult> Invoke<TContext, TResult>(TContext context, strin...
    method GetOrCreateRunner (line 33) | private ScriptRunner<TResult> GetOrCreateRunner<TContext, TResult>(str...
    method CreateRunner (line 49) | public ScriptRunner<TResult> CreateRunner<TContext, TResult>(string code)
    class MissingResolver (line 90) | private class MissingResolver : MetadataReferenceResolver
      method MissingResolver (line 92) | public MissingResolver(IMemoryCache cache)
      method Equals (line 99) | public override bool Equals(object other)
      method GetHashCode (line 104) | public override int GetHashCode()
      method ResolveReference (line 111) | public override ImmutableArray<PortableExecutableReference> ResolveR...
      method ResolveMissingAssembly (line 122) | public override PortableExecutableReference ResolveMissingAssembly(M...

FILE: src/Mockaco.AspNetCore/Templating/T4/TemplateSegment.cs
  type ISegment (line 32) | internal interface ISegment
  class TemplateSegment (line 39) | internal class TemplateSegment : ISegment
    method TemplateSegment (line 41) | public TemplateSegment(SegmentType type, string text, Location start)
  class Directive (line 55) | internal class Directive : ISegment
    method Directive (line 57) | public Directive(string name, Location start)
    method Extract (line 70) | public string Extract(string key)
  type SegmentType (line 79) | internal enum SegmentType
  type Location (line 87) | internal struct Location : IEquatable<Location>
    method Location (line 89) | public Location(string fileName, int line, int column)
    method AddLine (line 103) | public Location AddLine() => new Location(FileName, Line + 1, 1);
    method AddCol (line 105) | public Location AddCol() => AddCols(1);
    method AddCols (line 107) | public Location AddCols(int number) => new Location(FileName, Line, Co...
    method ToString (line 109) | public override string ToString() => $"[{FileName} ({Line},{Column})]";
    method Equals (line 111) | public bool Equals(Location other)

FILE: src/Mockaco.AspNetCore/Templating/T4/Tokeniser.cs
  class Tokeniser (line 31) | internal class Tokeniser
    method Tokeniser (line 42) | public Tokeniser(string fileName, string content)
    method Advance (line 49) | public bool Advance()
    method GetNextStateAndCurrentValue (line 61) | private State GetNextStateAndCurrentValue()
    method GetBlockEnd (line 92) | private State GetBlockEnd()
    method GetDirectiveName (line 127) | private State GetDirectiveName()
    method GetDirectiveValue (line 143) | private State GetDirectiveValue()
    method NextStateInContent (line 182) | private State NextStateInContent()
    method IsNewLine (line 239) | private int IsNewLine()
    method NextStateInDirective (line 254) | private State NextStateInDirective()
  type State (line 318) | internal enum State
  class ParserException (line 331) | internal class ParserException : Exception
    method ParserException (line 333) | public ParserException(string message, Location location)

FILE: src/Mockaco.AspNetCore/Templating/TemplateTransformer.cs
  class TemplateTransformer (line 9) | internal class TemplateTransformer : ITemplateTransformer
    method TemplateTransformer (line 14) | public TemplateTransformer(IScriptRunnerFactory scriptRunnerFactory, I...
    method TransformAndSetVariables (line 20) | public async Task<Template> TransformAndSetVariables(IRawTemplate rawT...
    method Transform (line 29) | public async Task<Template> Transform(IRawTemplate rawTemplate, IScrip...
    method Transform (line 47) | private async Task<string> Transform(string input, IScriptContext scri...
    method Run (line 92) | private async Task<object> Run(string code, IScriptContext scriptContext)

FILE: src/Mockaco.AspNetCore/Verifyer/VerifyerExtensions.cs
  class VerifyerExtensions (line 7) | internal static class VerifyerExtensions
    method Verify (line 9) | public static IResult Verify([FromQuery] string route, [FromServices] ...

FILE: src/Mockaco.AspNetCore/WarmUps/MockProviderWarmUp.cs
  class MockProviderWarmUp (line 5) | internal sealed class MockProviderWarmUp : IHostedService
    method MockProviderWarmUp (line 10) | public MockProviderWarmUp(IHostApplicationLifetime hostApplicationLife...
    method StartAsync (line 16) | public Task StartAsync(CancellationToken cancellationToken)
    method StopAsync (line 23) | public Task StopAsync(CancellationToken cancellationToken) => Task.Com...
    method OnStarted (line 25) | private void OnStarted()

FILE: src/Mockaco/Extensions/CommandLineExtensions.cs
  class CommandLineExtensions (line 3) | public static class CommandLineExtensions
    method IsUsingCommand (line 5) | public static bool IsUsingCommand(this Parser commandLine, string[] args)

FILE: src/Mockaco/Program.cs
  class Program (line 16) | public class Program
    method Main (line 18) | public static async Task Main(string[] args)
    method CreateHostBuilder (line 35) | public static IHostBuilder CreateHostBuilder(string[] args) =>
    method CreateCommandLineBuilder (line 55) | private static CommandLineBuilder CreateCommandLineBuilder(string[] ar...

FILE: src/Mockaco/Startup.Banner.cs
  class Startup (line 3) | public partial class Startup

FILE: src/Mockaco/Startup.cs
  class Startup (line 11) | public partial class Startup
    method Startup (line 15) | public Startup(IConfiguration configuration)
    method ConfigureServices (line 20) | public void ConfigureServices(IServiceCollection services)
    method Configure (line 27) | public void Configure(IApplicationBuilder app, ILogger<Startup> logger)

FILE: test/Mockaco.AspNetCore.Tests/Common/StringDictionaryTest.cs
  class StringDictionaryTests (line 5) | public class StringDictionaryTests
    method Add_WhenKeyNotExists_AddsKeyValue (line 7) | [Fact]
    method Add_WhenKeyExists_ReplacesValue (line 18) | [Fact]
    method Replace_WhenKeyNotExists_AddsKeyValue (line 31) | [Fact]
    method Replace_WhenKeyExists_ReplacesValue (line 42) | [Fact]
    method Indexer_Get_WhenKeyNotExists_ReturnsEmptyString (line 55) | [Fact]
    method Indexer_Set_UpdatesValue (line 64) | [Fact]

FILE: test/Mockaco.AspNetCore.Tests/Extensions/EnumerableExtensionTests.cs
  class EnumerableExtensionTests (line 3) | public class EnumerableExtensionTests
    method Select_Random_IEnumerables (line 5) | [Theory]
    method Data (line 16) | public static IEnumerable<object[]> Data()

FILE: test/Mockaco.AspNetCore.Tests/Extensions/StringExtensionsTests.cs
  class StringExtensionsTests (line 3) | public class StringExtensionsTests
    method Returns_False_For_Null_String (line 5) | [Fact]
    method Returns_False_For_Empty_String (line 12) | [Fact]
    method Returns_False_For_Relative_Path (line 19) | [Fact]
    method Returns_True_For_Absolute_Path (line 26) | [Fact]

FILE: test/Mockaco.AspNetCore.Tests/Middlewares/CallbackMiddlewareTest.cs
  class CallbackMiddlewareTest (line 7) | public class CallbackMiddlewareTest

FILE: test/Mockaco.AspNetCore.Tests/Middlewares/ErrorHandlingMiddlewareTest.cs
  class ErrorHandlingMiddlewareTest (line 16) | public class ErrorHandlingMiddlewareTest
    method ErrorHandlingMiddlewareTest (line 24) | public ErrorHandlingMiddlewareTest()
    method Writes_Unhandled_Exceptions_Thrown_In_Inner_Middlewares_As_Errors_In_Response_Body (line 33) | [Fact]
    method Writes_Mockaco_Context_Errors_To_Response_Body (line 56) | [Fact]
    method Includes_MockProvider_Errors_To_Response_Body_When_Any_Error_Occurs (line 79) | [Fact]
    method GetHttpContextForTest (line 98) | private static DefaultHttpContext GetHttpContextForTest()
    method ReadResponseBody (line 107) | private static async Task<string> ReadResponseBody(DefaultHttpContext ...

FILE: test/Mockaco.AspNetCore.Tests/Middlewares/RequestMatchingMiddlewareTest.cs
  class RequestMatchingMiddlewareTest (line 15) | public class RequestMatchingMiddlewareTest
    method RequestMatchingMiddlewareTest (line 19) | public RequestMatchingMiddlewareTest()
    method Attaches_Request_Parameters_To_Be_Accessible_Via_ScriptContext (line 26) | [Fact]

FILE: test/Mockaco.AspNetCore.Tests/Middlewares/ResponseDelayMiddlewareTest.cs
  class ResponseDelayMiddlewareTest (line 11) | public class ResponseDelayMiddlewareTest
    method ResponseDelayMiddlewareTest (line 19) | public ResponseDelayMiddlewareTest()
    method Modifies_Request_Duration (line 28) | [Theory]

FILE: test/Mockaco.AspNetCore.Tests/Middlewares/ResponseMockingMiddlewareTest.cs
  class ResponseMockingMiddlewareTest (line 13) | public class ResponseMockingMiddlewareTest
    method ResponseMockingMiddlewareTest (line 17) | public ResponseMockingMiddlewareTest()
    method Produces_Response_With_Default_Http_Status_When_Ommited_In_Template (line 23) | [Fact]

FILE: test/Mockaco.AspNetCore.Tests/Templating/Request/JsonRequestBodyStrategyTest.cs
  class JsonRequestBodyStrategyTest (line 13) | public sealed class JsonRequestBodyStrategyTest : IDisposable
    method Attaches_Request_With_Json_Body_With_Type (line 17) | [Theory]
    method Throws_Exception_When_Request_Has_Invalid_Json (line 43) | [Theory]
    method Can_Handle_Specific_ContentType (line 58) | [Theory]
    method PrepareHttpRequest (line 76) | private Moq.Mock<HttpRequest> PrepareHttpRequest(string givenBody, str...
    method Dispose (line 88) | public void Dispose() => _bodyStream.Dispose();

FILE: test/Mockaco.AspNetCore.Tests/Templating/Request/RequestConditionMatcherTest.cs
  class RequestConditionMatcherTest (line 9) | public sealed class RequestConditionMatcherTest
    method RequestConditionMatcherTest (line 18) | public RequestConditionMatcherTest()
    method Condition_Does_Not_Match_On_Script_Error (line 28) | [Fact]

FILE: test/Mockaco.AspNetCore.Tests/Templating/Response/BinaryResponseBodyStrategyTest.cs
  class BinaryResponseBodyStrategyTest (line 11) | public class BinaryResponseBodyStrategyTest
    method BinaryResponseBodyStrategyTest (line 15) | public BinaryResponseBodyStrategyTest()
    method Can_Handle_Templates_With_Response_File_Attribute (line 22) | [Fact]
    method Can_Handle_Templates_With_Response_Body_Attribute_And_Application_Octet_Stream_Content_Type (line 32) | [Fact]
    method Can_Not_Handle_Templates_With_Response_Body_Attribute_And_No_Content_Type (line 46) | [Fact]
    method Returns_Response_For_Binary_File (line 56) | [Fact]
    method Throws_When_Both_Body_And_File_Attributes_Are_Set (line 71) | [Fact]
    method Returns_Null_For_Null_Body (line 82) | [Fact]
    method Returns_Response_When_Body_Is_Set (line 93) | [Fact]

FILE: test/Mockaco.AspNetCore.Tests/Templating/Response/DefaultResponseBodyStrategyTest.cs
  class DefaultResponseBodyStrategyTest (line 6) | public class DefaultResponseBodyStrategyTest
    method DefaultResponseBodyStrategyTest (line 12) | public DefaultResponseBodyStrategyTest()
    method Can_Handle_Response_Template_With_Default_Properties (line 22) | [Fact]
    method Can_Handle_Response_Template_With_Content_Type (line 30) | [Fact]
    method Returns_Response_For_Any_Response_Template_By_Default (line 38) | [Fact]
    method Returns_Null_For_Null_Body (line 47) | [Fact]

FILE: test/Mockaco.AspNetCore.Tests/Templating/Response/JsonResponseBodyStrategyTest.cs
  class JsonResponseBodyStrategyTest (line 8) | public class JsonResponseBodyStrategyTest
    method JsonResponseBodyStrategyTest (line 18) | public JsonResponseBodyStrategyTest()
    method Can_Handle_Valid_Json_Response_Body_By_Default (line 25) | [Fact]
    method Can_Handle_Valid_Json_Response_Body_With_Application_Json_Content_Type_Header (line 33) | [Fact]
    method Can_Not_Handle_Valid_Json_Response_Body_With_Others_Content_Type_Header (line 43) | [Fact]
    method Returns_Response_With_Not_Indented_Valid_Json (line 53) | [Fact]
    method Returns_Response_With_Indented_Valid_Json (line 64) | [Fact]
    method Returns_Response_With_Indented_Valid_Json_By_Default (line 75) | [Fact]
    method Returns_Null_For_Null_Body (line 84) | [Fact]

FILE: test/Mockaco.AspNetCore.Tests/Templating/Response/ResponseBodyFactoryTest.cs
  class ResponseBodyFactoryTest (line 8) | public class ResponseBodyFactoryTest
    method Can_Handle_Null_Returned_From_Response_Body_Strategy (line 10) | [Fact]

FILE: test/Mockaco.AspNetCore.Tests/Templating/Response/XmlResponseBodyStrategyTest.cs
  class XmlResponseBodyStrategyTest (line 8) | public class XmlResponseBodyStrategyTest
    method XmlResponseBodyStrategyTest (line 24) | public XmlResponseBodyStrategyTest()
    method Can_Not_Handle_Response_Template_With_Default_Properties (line 29) | [Fact]
    method Can_Not_Handle_Response_Template_With_Other_Content_Type (line 38) | [Fact]
    method Can_Handle_Response_Template_With_Application_Xml_Content_Type (line 48) | [Fact]
    method Can_Handle_Response_Template_With_Text_Xml_Content_Type (line 58) | [Fact]
    method Returns_Response_With_Not_Indented_Valid_Xml (line 68) | [Fact]
    method Returns_Response_With_Indented_Valid_Xml (line 82) | [Fact]
    method Returns_Response_With_Indented_Valid_Xml_By_Default (line 96) | [Fact]

FILE: test/Mockaco.AspNetCore.Tests/Templating/Scripting/LocalizedFakerFactoryTest.cs
  class LocalizedFakerFactoryTest (line 8) | public class LocalizedFakerFactoryTest
    method LocalizedFakerFactoryTest (line 12) | public LocalizedFakerFactoryTest()
    method Gets_Localized_Faker_Based_On_Http_Accept_Language_Header (line 17) | [Fact]
    method Gets_Default_Faker_When_No_Accept_Language_Header_Is_Present (line 25) | [Fact]

FILE: test/Mockaco.AspNetCore.Tests/Templating/Scripting/ScriptRunnerFactoryTest.cs
  class ScriptRunnerFactoryTest (line 6) | public class ScriptRunnerFactoryTest
    method Can_Run_Scripts_From_Builtin_Namespaces (line 8) | [Theory]

FILE: test/Mockaco.AspNetCore.Tests/Templating/TemplateTransformerTest.cs
  class TemplateTransformerTest (line 11) | public class TemplateTransformerTest
    method Transforms_Plain_Json_Template (line 13) | [Theory]
    method Transforms_Scripted_Json_Template (line 28) | [Theory]
    method Assert (line 48) | private static void Assert(Template transformedTemplate)

FILE: test/Mockaco.AspNetCore.Tests/TextFileDataAttribute.cs
  class TextFileDataAttribute (line 9) | public class TextFileDataAttribute : DataAttribute
    method TextFileDataAttribute (line 13) | public TextFileDataAttribute(string filePath)
    method GetData (line 18) | public override IEnumerable<object[]> GetData(MethodInfo testMethod)

FILE: website/src/components/HomepageFeatures/index.js
  function Feature (line 35) | function Feature({Svg, title, description}) {
  function HomepageFeatures (line 49) | function HomepageFeatures() {

FILE: website/src/pages/index.js
  function HomepageHeader (line 10) | function HomepageHeader() {
  function Home (line 42) | function Home() {

FILE: website/src/pages/videos.js
  function Videos (line 7) | function Videos() {
Condensed preview — 215 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (352K chars).
[
  {
    "path": ".dockerignore",
    "chars": 4457,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User"
  },
  {
    "path": ".editorconfig",
    "chars": 513,
    "preview": "[*.{cs,vb}]\ndotnet_naming_rule.private_members_with_underscore.symbols  = private_fields\ndotnet_naming_rule.private_memb"
  },
  {
    "path": ".gitattributes",
    "chars": 2518,
    "preview": "###############################################################################\n# Set default behavior to automatically "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/01_feature_request.yml",
    "chars": 1503,
    "preview": "---\nname: 🚀 Feature request\ndescription: Suggest an idea for this project\nlabels: [\"enhancement\"]\nbody:\n  - type: checkb"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/02_bug_report.yml",
    "chars": 1459,
    "preview": "---\nname: 🐛 Bug report\ndescription: Create a report to help us improve\nlabels: [\"bug\"]\nbody:\n  - type: checkboxes\n    id"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 28,
    "preview": "blank_issues_enabled: false\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/pull_request_template.md",
    "chars": 450,
    "preview": "*Thank you for your contribution to the Mockaco 🐵 repo!*\n\nBefore submitting this PR, please make sure:\n\n- [ ] There is a"
  },
  {
    "path": ".github/workflows/main-release.yml",
    "chars": 3471,
    "preview": "name: Main Release\n\non:\n  workflow_dispatch:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - "
  },
  {
    "path": ".github/workflows/website-deploy-test.yml",
    "chars": 540,
    "preview": "name: Deploy to GitHub Pages (Test)\n\non:\n  pull_request:\n    branches:\n      - master\n\ndefaults:\n  run:\n    working-dire"
  },
  {
    "path": ".github/workflows/website-deploy.yml",
    "chars": 1563,
    "preview": "name: Deploy to GitHub Pages\n\non:\n  push:\n    branches:\n      - master\n    # Review gh actions docs if you want to furth"
  },
  {
    "path": ".gitignore",
    "chars": 4396,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3349,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1434,
    "preview": "## How to contribute to Mockaco\n\nIt's great you're reading this, because we need volunteer developers to help this proje"
  },
  {
    "path": "LICENSE",
    "chars": 13988,
    "preview": "   Mockaco - Copyright (c) 2019-2021 Renato Lima\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   "
  },
  {
    "path": "Mockaco.sln",
    "chars": 2716,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.1.3221"
  },
  {
    "path": "README.md",
    "chars": 2535,
    "preview": "<p align=\"center\">\n    <img src=\"https://github.com/natenho/Mockaco/raw/master/src/Mockaco/Resources/mockaco-logo.svg\" w"
  },
  {
    "path": "appveyor.yml",
    "chars": 1079,
    "preview": "pull_requests:\n  do_not_increment_build_number: true\nskip_non_tags: true\nimage: Visual Studio 2019\nconfiguration: Releas"
  },
  {
    "path": "checkBuild.ps1",
    "chars": 771,
    "preview": "dotnet restore --verbosity normal\ndotnet build --configuration Release --verbosity normal .\\src\\Mockaco\\Mockaco.csproj\nd"
  },
  {
    "path": "src/Mockaco/.dockerignore",
    "chars": 349,
    "preview": "**/.classpath\n**/.dockerignore\n**/.env\n**/.git\n**/.gitignore\n**/.project\n**/.settings\n**/.toolstarget\n**/.vs\n**/.vscode\n"
  },
  {
    "path": "src/Mockaco/Docker/Dockerfile",
    "chars": 1074,
    "preview": "FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS base\nWORKDIR /app\nEXPOSE 5000\nEXPOSE 5443\n\nFROM mcr.microsoft.com/dot"
  },
  {
    "path": "src/Mockaco/Docker/README.md",
    "chars": 2460,
    "preview": "# Quick reference\n\n-\t**Where to get help and to file issues**:  \n\t[GitHub repository](https://github.com/natenho/Mockaco"
  },
  {
    "path": "src/Mockaco/Extensions/CommandLineExtensions.cs",
    "chars": 337,
    "preview": "namespace System.CommandLine.Parsing\n{\n    public static class CommandLineExtensions\n    {\n        public static bool I"
  },
  {
    "path": "src/Mockaco/Mockaco.csproj",
    "chars": 3276,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n\t<PropertyGroup>\n\t\t<TargetFramework>net6.0</TargetFramework>\n\t\t<LangVersion>late"
  },
  {
    "path": "src/Mockaco/Mocks/hello.json",
    "chars": 278,
    "preview": "{\n  \"request\": {\n    \"method\": \"GET\",\n    \"route\": \"hello/{message}\"\n  },\n  \"response\": {\n    \"body\": {\n\t\t\"id\": \"<#= Fak"
  },
  {
    "path": "src/Mockaco/Program.cs",
    "chars": 2293,
    "preview": "using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.Hosting;\nusing"
  },
  {
    "path": "src/Mockaco/Properties/PublishProfiles/FolderProfile.pubxml",
    "chars": 943,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\nThis file is used by the publish/package process of your Web project. You ca"
  },
  {
    "path": "src/Mockaco/Properties/launchSettings.json",
    "chars": 279,
    "preview": "{\n  \"$schema\": \"http://json.schemastore.org/launchsettings.json\",\n  \"profiles\": {\n    \"Mockaco\": {\n      \"commandName\": "
  },
  {
    "path": "src/Mockaco/Settings/appsettings.Development.json",
    "chars": 392,
    "preview": "{\n  \"Mockaco\": {\n    \"TemplateFileProvider\": {\n      \"Path\": \"Mocks\"\n    }\n  },\n  \"Serilog\": {\n    \"WriteTo\": [\n      {\n"
  },
  {
    "path": "src/Mockaco/Settings/appsettings.Docker.json",
    "chars": 122,
    "preview": "{\n  \"Urls\": \"http://+:5000;https://+:5443\",\n  \"Mockaco\": {\n    \"TemplateFileProvider\": {\n      \"Path\": \"Mocks\"\n    }\n  }"
  },
  {
    "path": "src/Mockaco/Settings/appsettings.Production.json",
    "chars": 346,
    "preview": "{\n  \"Urls\": \"http://127.0.0.1:0\",\n  \"Serilog\": {\n    \"WriteTo\": [\n      {\n      },\n      {\n        \"Name\": \"File\",\n     "
  },
  {
    "path": "src/Mockaco/Settings/appsettings.json",
    "chars": 1208,
    "preview": "{\n  \"Mockaco\": {\n    \"DefaultHttpStatusCode\": \"OK\",\n    \"ErrorHttpStatusCode\": \"NotImplemented\",\n    \"DefaultHttpContent"
  },
  {
    "path": "src/Mockaco/Startup.Banner.cs",
    "chars": 3488,
    "preview": "namespace Mockaco\n{\n    public partial class Startup\n    {\n        private const string _logo =\n        \"              "
  },
  {
    "path": "src/Mockaco/Startup.cs",
    "chars": 1331,
    "preview": "using Microsoft.AspNetCore.Builder;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInje"
  },
  {
    "path": "src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyBehavior.cs",
    "chars": 512,
    "preview": "using System.Net;\nusing System.Text;\nusing Microsoft.AspNetCore.Http;\n\nnamespace Mockaco.Chaos.Strategies;\n\ninternal cla"
  },
  {
    "path": "src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyException.cs",
    "chars": 506,
    "preview": "using System.Net;\nusing System.Text;\nusing Microsoft.AspNetCore.Http;\n\nnamespace Mockaco.Chaos.Strategies;\n\ninternal cla"
  },
  {
    "path": "src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyLatency.cs",
    "chars": 777,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Options;\n\nnamespace Mock"
  },
  {
    "path": "src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyResult.cs",
    "chars": 485,
    "preview": "using System.Net;\nusing System.Text;\nusing Microsoft.AspNetCore.Http;\n\nnamespace Mockaco.Chaos.Strategies;\n\ninternal cla"
  },
  {
    "path": "src/Mockaco.AspNetCore/Chaos/Strategies/ChaosStrategyTimeout.cs",
    "chars": 769,
    "preview": "using System.Net;\nusing System.Text;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Options;\n\nnamespace Moc"
  },
  {
    "path": "src/Mockaco.AspNetCore/Chaos/Strategies/IChaosStrategy.cs",
    "chars": 154,
    "preview": "using Microsoft.AspNetCore.Http;\n\nnamespace Mockaco.Chaos.Strategies;\n\ninternal interface IChaosStrategy\n{\n    Task Resp"
  },
  {
    "path": "src/Mockaco.AspNetCore/Common/HttpContentTypes.cs",
    "chars": 338,
    "preview": "namespace Mockaco\n{\n    internal static class HttpContentTypes\n    {\n        public const string ApplicationOctetStream"
  },
  {
    "path": "src/Mockaco.AspNetCore/Common/HttpHeaders.cs",
    "chars": 194,
    "preview": "namespace Mockaco\n{\n    internal static class HttpHeaders\n    {\n        public const string ContentType = \"Content-Type"
  },
  {
    "path": "src/Mockaco.AspNetCore/Common/InvalidMockException.cs",
    "chars": 650,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.Serialization;\nusing System.Tex"
  },
  {
    "path": "src/Mockaco.AspNetCore/Common/RouteMatcher.cs",
    "chars": 1229,
    "preview": "using Microsoft.AspNetCore.Routing;\nusing Microsoft.AspNetCore.Routing.Template;\n\nnamespace Mockaco\n{\n    internal clas"
  },
  {
    "path": "src/Mockaco.AspNetCore/Common/SimpleExceptionConverter.cs",
    "chars": 1396,
    "preview": "namespace Mockaco.Common\n{\n    using Newtonsoft.Json;\n    using Newtonsoft.Json.Linq;\n    using System;\n\n    internal c"
  },
  {
    "path": "src/Mockaco.AspNetCore/Common/StringDictionary.cs",
    "chars": 828,
    "preview": "using System.Collections.Generic;\n\nnamespace Mockaco\n{\n    public class StringDictionary : Dictionary<string, string>, "
  },
  {
    "path": "src/Mockaco.AspNetCore/DependencyInjection/MockacoApplicationBuilder.cs",
    "chars": 1935,
    "preview": "using Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Options;\nusing Mockaco;\nusing Mockaco.Verify"
  },
  {
    "path": "src/Mockaco.AspNetCore/DependencyInjection/MockacoServiceCollection.cs",
    "chars": 4449,
    "preview": "using Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.Diagnostics.HealthChecks;\nusing Microsoft.Extensio"
  },
  {
    "path": "src/Mockaco.AspNetCore/Extensions/EnumerableExtensions.cs",
    "chars": 1465,
    "preview": "using System.Threading.Tasks;\n\nnamespace System.Collections.Generic\n{\n    internal static class EnumerableExtensions\n  "
  },
  {
    "path": "src/Mockaco.AspNetCore/Extensions/HttpRequestExtensions.cs",
    "chars": 4650,
    "preview": "/*\nThe MIT License (MIT)\n\nCopyright (c) 2015 Microsoft\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "src/Mockaco.AspNetCore/Extensions/ObjectExtensions.cs",
    "chars": 1201,
    "preview": "using Mockaco.Common;\nusing Newtonsoft.Json;\nusing Newtonsoft.Json.Converters;\nusing Newtonsoft.Json.Serialization;\nusi"
  },
  {
    "path": "src/Mockaco.AspNetCore/Extensions/StringDictionaryExtensions.cs",
    "chars": 680,
    "preview": "using Mockaco;\n\nnamespace System.Collections.Generic\n{\n    internal static class StringDictionaryExtensions\n    {\n     "
  },
  {
    "path": "src/Mockaco.AspNetCore/Extensions/StringExtensions.cs",
    "chars": 921,
    "preview": "using System.Text;\n\nnamespace System\n{\n    internal static class StringExtensions\n    {\n        public static string To"
  },
  {
    "path": "src/Mockaco.AspNetCore/HealthChecks/StartupHealthCheck.cs",
    "chars": 728,
    "preview": "using Microsoft.Extensions.Diagnostics.HealthChecks;\n\nnamespace Mockaco.HealthChecks\n{\n    public class StartupHealthCh"
  },
  {
    "path": "src/Mockaco.AspNetCore/IMockProvider.cs",
    "chars": 269,
    "preview": "using System.Collections.Generic;\nusing System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    internal interface IMockProvid"
  },
  {
    "path": "src/Mockaco.AspNetCore/IMockacoContext.cs",
    "chars": 281,
    "preview": "using System.Collections.Generic;\n\nnamespace Mockaco\n{\n    internal interface IMockacoContext\n    {\n        IScriptCont"
  },
  {
    "path": "src/Mockaco.AspNetCore/InternalsVisibleTo.cs",
    "chars": 159,
    "preview": "using System.Runtime.CompilerServices;\n\n[assembly: InternalsVisibleTo(\"Mockaco.AspNetCore.Tests\")]\n[assembly: Internals"
  },
  {
    "path": "src/Mockaco.AspNetCore/Middlewares/CallbackMiddleware.cs",
    "chars": 6717,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Logging;\nus"
  },
  {
    "path": "src/Mockaco.AspNetCore/Middlewares/ChaosMiddleware.cs",
    "chars": 1907,
    "preview": "using System.Net;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Option"
  },
  {
    "path": "src/Mockaco.AspNetCore/Middlewares/ErrorHandlingMiddleware.cs",
    "chars": 1849,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Options;\nusing System;\n"
  },
  {
    "path": "src/Mockaco.AspNetCore/Middlewares/RequestMatchingMiddleware.cs",
    "chars": 4397,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing System;\nusing System.Collections.Generic;\nus"
  },
  {
    "path": "src/Mockaco.AspNetCore/Middlewares/ResponseDelayMiddleware.cs",
    "chars": 1029,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing System.Diagnostics;\nusing System.Threading.T"
  },
  {
    "path": "src/Mockaco.AspNetCore/Middlewares/ResponseMockingMiddleware.cs",
    "chars": 2541,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Options;\nusing System.Net;\nusing System.Threading.Tasks;\n\nn"
  },
  {
    "path": "src/Mockaco.AspNetCore/MockProvider.cs",
    "chars": 5046,
    "preview": "using Microsoft.Extensions.Diagnostics.HealthChecks;\nusing Microsoft.Extensions.Logging;\nusing Mockaco.HealthChecks;\nus"
  },
  {
    "path": "src/Mockaco.AspNetCore/Mockaco.AspNetCore.csproj",
    "chars": 3154,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<TargetFramework>net6.0</TargetFramework>\n\t\t<LangVersion>latest</"
  },
  {
    "path": "src/Mockaco.AspNetCore/MockacoContext.cs",
    "chars": 508,
    "preview": "using System.Collections.Generic;\n\nnamespace Mockaco\n{\n    internal class MockacoContext : IMockacoContext\n    {\n      "
  },
  {
    "path": "src/Mockaco.AspNetCore/Options/ChaosOptions.cs",
    "chars": 461,
    "preview": "namespace Mockaco;\n\npublic class ChaosOptions\n{\n    public bool Enabled { get; set; }\n    public int ChaosRate { get; se"
  },
  {
    "path": "src/Mockaco.AspNetCore/Options/MockacoOptions.cs",
    "chars": 1450,
    "preview": "using System.Net;\n\nnamespace Mockaco\n{\n    public class MockacoOptions\n    {\n        public HttpStatusCode DefaultHttpS"
  },
  {
    "path": "src/Mockaco.AspNetCore/Options/TemplateFileProviderOptions.cs",
    "chars": 313,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace Mockaco\n{\n "
  },
  {
    "path": "src/Mockaco.AspNetCore/Plugins/PhoneNumberExtensions.cs",
    "chars": 894,
    "preview": "using Bogus.DataSets;\n\nnamespace Bogus\n{\n    // TODO Move to plugin\n    public static class PhoneNumberExtensions\n    {"
  },
  {
    "path": "src/Mockaco.AspNetCore/PublicAPI.Shipped.txt",
    "chars": 1,
    "preview": ""
  },
  {
    "path": "src/Mockaco.AspNetCore/PublicAPI.Unshipped.txt",
    "chars": 9560,
    "preview": "Bogus.PhoneNumberExtensions\nMicrosoft.AspNetCore.Builder.MockacoApplicationBuilder\nMicrosoft.Extensions.DependencyInjec"
  },
  {
    "path": "src/Mockaco.AspNetCore/Settings/VerificationRouteValueTransformer.cs",
    "chars": 561,
    "preview": "namespace Mockaco.Settings\n{\n    using System.Threading.Tasks;\n    using Microsoft.AspNetCore.Http;\n    using Microsoft"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Cli/GeneratorRunner.cs",
    "chars": 786,
    "preview": "using System;\nusing System.CommandLine;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/GeneratedTemplate.cs",
    "chars": 144,
    "preview": "namespace Mockaco.Templating.Generating\n{\n    internal class GeneratedTemplate : Template\n    {\n        public string Na"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/GeneratingOptions.cs",
    "chars": 769,
    "preview": "using System;\nusing System.IO;\n\nnamespace Mockaco.Templating.Generating\n{\n    internal class GeneratingOptions\n    {\n   "
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Providers/GeneratedTemplateProviderFactory.cs",
    "chars": 1044,
    "preview": "using System;\nusing System.Collections.Generic;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Mockaco.Templ"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Providers/IGeneratedTemplateProvider.cs",
    "chars": 353,
    "preview": "using System.Collections.Generic;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Mock"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Providers/IGeneratedTemplateProviderFactory.cs",
    "chars": 186,
    "preview": "namespace Mockaco.Templating.Generating.Providers\n{\n    internal interface IGeneratedTemplateProviderFactory\n    {\n     "
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Providers/OpenApiTemplateProvider.cs",
    "chars": 4184,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Net;\nusing System.Threa"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/ServiceCollectionExtensions.cs",
    "chars": 1938,
    "preview": "using Mockaco.Templating.Generating;\nusing Mockaco.Templating.Generating.Cli;\nusing Mockaco.Templating.Generating.Provid"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Source/HttpContentProvider.cs",
    "chars": 444,
    "preview": "using System;\nusing System.IO;\nusing System.Net.Http;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace M"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Source/ISourceContentProvider.cs",
    "chars": 285,
    "preview": "using System;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Mockaco.Templating.Gene"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Source/LocalFileContentProvider.cs",
    "chars": 414,
    "preview": "using System;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Mockaco.Templating.Gene"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Source/SourceContentProviderComposite.cs",
    "chars": 1956,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Store/GeneratedTemplateStore.cs",
    "chars": 2477,
    "preview": "using System.Collections.Generic;\nusing System.IO;\nusing System.Text.Json;\nusing System.Threading;\nusing System.Threadin"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Store/IGeneratedTemplateStore.cs",
    "chars": 418,
    "preview": "using System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Mockaco.Templating.Ge"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/Store/TemplateStoreOptions.cs",
    "chars": 145,
    "preview": "namespace Mockaco.Templating.Generating.Store\n{\n    internal class TemplateStoreOptions\n    {\n        public string Root"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Generating/TemplatesGenerator.cs",
    "chars": 1298,
    "preview": "using System.Threading;\nusing System.Threading.Tasks;\nusing Mockaco.Templating.Generating.Providers;\nusing Mockaco.Templ"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/ITemplateTransformer.cs",
    "chars": 345,
    "preview": "using System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    internal interface ITemplateTransformer\n    {\n        //TODO Imp"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Models/CallbackTemplate.cs",
    "chars": 454,
    "preview": "using Newtonsoft.Json.Linq;\nusing System.Collections.Generic;\n\nnamespace Mockaco\n{\n    internal class CallbackTemplate\n"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Models/Error.cs",
    "chars": 490,
    "preview": "using System;\n\nnamespace Mockaco\n{\n    internal class Error\n    {\n        public string Message { get; }\n\n        publi"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Models/IRawTemplate.cs",
    "chars": 160,
    "preview": "namespace Mockaco\n{\n    public interface IRawTemplate\n    {\n        string Content { get; }\n\n        string Name { get;"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Models/Mock.cs",
    "chars": 710,
    "preview": "using System.Diagnostics;\n\nnamespace Mockaco\n{\n    [DebuggerDisplay(\"{Method} {Route} ({RawTemplate.Name})\")]\n    publi"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Models/RawTemplate.cs",
    "chars": 439,
    "preview": "using System;\nusing System.Diagnostics;\n\nnamespace Mockaco\n{\n    [DebuggerDisplay(\"{Name}\")]\n    internal class RawTemp"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Models/RequestTemplate.cs",
    "chars": 201,
    "preview": "namespace Mockaco\n{\n    internal class RequestTemplate\n    {\n        public string Method { get; set; }\n\n        public"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Models/ResponseTemplate.cs",
    "chars": 537,
    "preview": "using Newtonsoft.Json.Linq;\nusing System.Collections.Generic;\nusing System.Net;\n\nnamespace Mockaco\n{\n    public class R"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Models/Template.cs",
    "chars": 587,
    "preview": "using System.Collections.Generic;\nusing System.Linq;\n\nnamespace Mockaco\n{\n    internal class Template\n    {\n        pub"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Providers/ITemplateProvider.cs",
    "chars": 212,
    "preview": "using System;\nusing System.Collections.Generic;\n\nnamespace Mockaco\n{\n    internal interface ITemplateProvider\n    {\n   "
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Providers/TemplateFileProvider.cs",
    "chars": 7308,
    "preview": "using MAB.DotIgnore;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Caching.Memory;\nusing Microsoft.Ext"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Request/FormRequestBodyStrategy.cs",
    "chars": 550,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Newtonsoft.Json.Linq;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespac"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Request/IRequestBodyFactory.cs",
    "chars": 230,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Newtonsoft.Json.Linq;\nusing System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    pub"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Request/IRequestBodyStrategy.cs",
    "chars": 281,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Newtonsoft.Json.Linq;\nusing System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    int"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Request/IRequestMatcher.cs",
    "chars": 201,
    "preview": "using Microsoft.AspNetCore.Http;\nusing System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    internal interface IRequestMatc"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Request/JsonRequestBodyStrategy.cs",
    "chars": 632,
    "preview": "\nusing Microsoft.AspNetCore.Http;\nusing Newtonsoft.Json.Linq;\nusing System.Threading.Tasks;\n\n\nnamespace Mockaco\n{\n    i"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Request/RequestBodyFactory.cs",
    "chars": 954,
    "preview": "using System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Http;\nusi"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Request/RequestConditionMatcher.cs",
    "chars": 2875,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing Newtonsoft.Json;\n\nnamespace Mockaco\n{\n    in"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Request/RequestMethodMatcher.cs",
    "chars": 583,
    "preview": "using Microsoft.AspNetCore.Http;\nusing System;\nusing System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    internal class Re"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Request/RequestRouteMatcher.cs",
    "chars": 615,
    "preview": "using Microsoft.AspNetCore.Http;\nusing System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    internal class RequestRouteMatc"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Request/XmlRequestBodyStrategy.cs",
    "chars": 826,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\nusing System.Threading.Tasks;\nusing"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Response/BinaryResponseBodyStrategy.cs",
    "chars": 1966,
    "preview": "using System;\nusing System.IO;\nusing System.Net.Http;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Mocka"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Response/DefaultResponseBodyStrategy.cs",
    "chars": 405,
    "preview": "namespace Mockaco\n{\n    internal class DefaultResponseBodyStrategy : StringResponseBodyStrategy\n    {\n        public ov"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Response/IResponseBodyFactory.cs",
    "chars": 200,
    "preview": "using System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    internal interface IResponseBodyFactory\n    {\n        Task<byte["
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Response/IResponseBodyStrategy.cs",
    "chars": 260,
    "preview": "using System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    internal interface IResponseBodyStrategy\n    {\n        bool CanH"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Response/JsonResponseBodyStrategy.cs",
    "chars": 712,
    "preview": "using Newtonsoft.Json;\n\nnamespace Mockaco\n{\n    internal class JsonResponseBodyStrategy : StringResponseBodyStrategy\n  "
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Response/ResponseBodyFactory.cs",
    "chars": 892,
    "preview": "using System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    internal cl"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Response/StringResponseBodyStrategy.cs",
    "chars": 707,
    "preview": "using System.Text;\nusing System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    internal abstract class StringResponseBodyStr"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Response/XmlResponseBodyStrategy.cs",
    "chars": 1103,
    "preview": "using System;\nusing System.Text;\nusing System.Xml;\n\nnamespace Mockaco\n{\n    internal class XmlResponseBodyStrategy : St"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Scripting/IFakerFactory.cs",
    "chars": 217,
    "preview": "using Bogus;\nusing System.Collections.Generic;\n\nnamespace Mockaco\n{\n    public interface IFakerFactory\n    {\n        Fa"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Scripting/IGlobalVarialeStorage.cs",
    "chars": 211,
    "preview": "namespace Mockaco\n{\n    public interface IGlobalVariableStorage\n    {\n        object this[string name] { get; set; }\n\n "
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Scripting/IScriptContext.cs",
    "chars": 550,
    "preview": "using Bogus;\nusing Microsoft.AspNetCore.Http;\nusing System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    public interface I"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Scripting/IScriptRunnerFactory.cs",
    "chars": 306,
    "preview": "using Microsoft.CodeAnalysis.Scripting;\nusing System.Threading.Tasks;\n\nnamespace Mockaco\n{\n    internal interface IScri"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Scripting/LocalizedFakerFactory.cs",
    "chars": 2174,
    "preview": "using Bogus;\nusing Bogus.Extensions;\nusing Microsoft.Extensions.Logging;\nusing System.Collections.Generic;\nusing System"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Scripting/ScriptContext.cs",
    "chars": 2951,
    "preview": "using Bogus;\nusing Microsoft.AspNetCore.Http;\nusing Newtonsoft.Json.Linq;\nusing System;\nusing System.Collections.Generi"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Scripting/ScriptContextGlobalVariableStorage.cs",
    "chars": 1147,
    "preview": "using System.Collections.Concurrent;\n\nnamespace Mockaco\n{\n    internal class ScriptContextGlobalVariableStorage : IGlob"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Scripting/ScriptContextRequest.cs",
    "chars": 827,
    "preview": "using Newtonsoft.Json.Linq;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Mockaco\n{\n    public class Scrip"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Scripting/ScriptContextResponse.cs",
    "chars": 390,
    "preview": "using Newtonsoft.Json.Linq;\nusing System.Collections.Generic;\n\nnamespace Mockaco\n{\n    public class ScriptContextRespon"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/Scripting/ScriptRunnerFactory.cs",
    "chars": 4996,
    "preview": "using Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp.Scripting;\nusing Microsoft.CodeAnalysis.Scripting;\nus"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/T4/TemplateSegment.cs",
    "chars": 3709,
    "preview": "// \n// Template.cs\n//  \n// Author:\n//       Mikayla Hutchinson <m.j.hutchinson@gmail.com>\n// \n// Copyright (c) 2009 Nov"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/T4/Tokeniser.cs",
    "chars": 12371,
    "preview": "// \n// Tokeniser.cs\n//  \n// Author:\n//       Mikayla Hutchinson <m.j.hutchinson@gmail.com>\n// \n// Copyright (c) 2009 No"
  },
  {
    "path": "src/Mockaco.AspNetCore/Templating/TemplateTransformer.cs",
    "chars": 3691,
    "preview": "using Microsoft.Extensions.Logging;\nusing Mockaco.Common;\nusing Mono.TextTemplating;\nusing Newtonsoft.Json;\nusing Syste"
  },
  {
    "path": "src/Mockaco.AspNetCore/Verifyer/VerifyerExtensions.cs",
    "chars": 573,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.Extensions.Caching.Memory;\n\nnamespace "
  },
  {
    "path": "src/Mockaco.AspNetCore/WarmUps/MockProviderWarmUp.cs",
    "chars": 890,
    "preview": "using Microsoft.Extensions.Hosting;\n\nnamespace Mockaco\n{\n    internal sealed class MockProviderWarmUp : IHostedService\n"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Common/StringDictionaryTest.cs",
    "chars": 2073,
    "preview": "using Xunit;\nusing Mockaco;\nusing FluentAssertions;\n\npublic class StringDictionaryTests\n{\n    [Fact]\n    public void Add"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Extensions/EnumerableExtensionTests.cs",
    "chars": 616,
    "preview": "namespace Mockaco.Tests.Extensions;\n\npublic class EnumerableExtensionTests\n{\n    [Theory]\n    [MemberData(nameof(Data))]"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Extensions/StringExtensionsTests.cs",
    "chars": 768,
    "preview": "namespace Mockaco.AspNetCore.Tests.Extensions;\n\npublic class StringExtensionsTests\n{\n    [Fact]\n    public void Returns_"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Middlewares/CallbackMiddlewareTest.cs",
    "chars": 161,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Mockaco.Tests.Middlewares\n{\n    public cl"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Middlewares/ErrorHandlingMiddlewareTest.cs",
    "chars": 4538,
    "preview": "using FluentAssertions;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Middlewares/RequestMatchingMiddlewareTest.cs",
    "chars": 2611,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing System;\nusing System.Collections.Generic;\nus"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Middlewares/ResponseDelayMiddlewareTest.cs",
    "chars": 1518,
    "preview": "using FluentAssertions;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing Moq;\nusing System.Di"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Middlewares/ResponseMockingMiddlewareTest.cs",
    "chars": 2050,
    "preview": "using FluentAssertions;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Options;\nusing Moq;\nusing System.Co"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Mockaco.AspNetCore.Tests.csproj",
    "chars": 1825,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<TargetFramework>net6.0</TargetFramework>\n\t\t<RootNamespace>Mockac"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/Request/JsonRequestBodyStrategyTest.cs",
    "chars": 3213,
    "preview": "using FluentAssertions;\nusing Microsoft.AspNetCore.Http;\nusing Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\nusing Syste"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/Request/RequestConditionMatcherTest.cs",
    "chars": 2221,
    "preview": "using FluentAssertions;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing Moq;\nusing System.Ne"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/Response/BinaryResponseBodyStrategyTest.cs",
    "chars": 3368,
    "preview": "using FluentAssertions;\nusing System;\nusing System.IO;\nusing System.Net.Http;\nusing System.Text;\nusing System.Threading"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/Response/DefaultResponseBodyStrategyTest.cs",
    "chars": 1761,
    "preview": "using FluentAssertions;\nusing Xunit;\n\nnamespace Mockaco.Tests.Templating\n{\n    public class DefaultResponseBodyStrategy"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/Response/JsonResponseBodyStrategyTest.cs",
    "chars": 3013,
    "preview": "using FluentAssertions;\nusing Newtonsoft.Json.Linq;\nusing Xunit;\nusing System;\n\nnamespace Mockaco.Tests.Templating\n{\n  "
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/Response/ResponseBodyFactoryTest.cs",
    "chars": 849,
    "preview": "using FluentAssertions;\nusing Moq;\nusing System.Threading.Tasks;\nusing Xunit;\n\nnamespace Mockaco.Tests.Templating.Respo"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/Response/XmlResponseBodyStrategyTest.cs",
    "chars": 4492,
    "preview": "using FluentAssertions;\nusing Newtonsoft.Json.Linq;\nusing System;\nusing Xunit;\n\nnamespace Mockaco.Tests.Templating\n{\n  "
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/Scripting/LocalizedFakerFactoryTest.cs",
    "chars": 926,
    "preview": "using FluentAssertions;\nusing Microsoft.Extensions.Logging;\nusing System.Linq;\nusing Xunit;\n\nnamespace Mockaco.Tests.Sc"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/Scripting/ScriptRunnerFactoryTest.cs",
    "chars": 1171,
    "preview": "using Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Options;\n\nnamespace Mockaco.Tests.Templating.Scripting\n{"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/TemplateTransformerTest.cs",
    "chars": 4853,
    "preview": "using FluentAssertions;\nusing Microsoft.Extensions.Logging;\nusing Newtonsoft.Json.Linq;\nusing System;\nusing System.Net;"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/Transforms_Plain_Json_Template.json",
    "chars": 765,
    "preview": "{\n  \"request\": {\n    \"method\": \"POST\",\n    \"route\": \"this/is/the/{parameter1}/route/{parameter2}\",\n    \"condition\": true"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Templating/Transforms_Scripted_Json_Template.json",
    "chars": 911,
    "preview": "{\n  \"request\": {\n    \"method\": \"POST\",\n    \"route\": \"this/is/the/{parameter1}/route/{parameter2}\",\n    \"condition\": \"<#="
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/TextFileDataAttribute.cs",
    "chars": 1029,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Reflection;\nusing Xunit.Sdk;\n\nnamespace M"
  },
  {
    "path": "test/Mockaco.AspNetCore.Tests/Usings.cs",
    "chars": 19,
    "preview": "global using Xunit;"
  },
  {
    "path": "test/_postman/Mockaco.postman_collection.json",
    "chars": 1556,
    "preview": "{\n\t\"info\": {\n\t\t\"_postman_id\": \"53119370-0818-4475-9413-cd931b81d1f5\",\n\t\t\"name\": \"Mockaco\",\n\t\t\"schema\": \"https://schema.g"
  },
  {
    "path": "website/.gitignore",
    "chars": 233,
    "preview": "# Dependencies\n/node_modules\n\n# Production\n/build\n\n# Generated files\n.docusaurus\n.cache-loader\n\n# Misc\n.DS_Store\n.env.lo"
  },
  {
    "path": "website/README.md",
    "chars": 770,
    "preview": "# Website\n\nThis website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.\n\n### I"
  },
  {
    "path": "website/babel.config.js",
    "chars": 89,
    "preview": "module.exports = {\n  presets: [require.resolve('@docusaurus/core/lib/babel/preset')],\n};\n"
  },
  {
    "path": "website/blog/authors.yml",
    "chars": 137,
    "preview": "natenho:\n  name: Renato Lima\n  title: Maintainer of Mockaco\n  url: https://github.com/natenho\n  image_url: https://githu"
  },
  {
    "path": "website/docs/chaos/index.md",
    "chars": 1900,
    "preview": "# Chaos Engineering\n\nEnabling chaos engineering, behavior different from what is expected will be randomly inserted into"
  },
  {
    "path": "website/docs/configuration/_category_.json",
    "chars": 48,
    "preview": "{\n  \"label\": \"Configuration\",\n  \"position\": 7\n}\n"
  },
  {
    "path": "website/docs/configuration/index.md",
    "chars": 4096,
    "preview": "# Configuration\n\n### App Settings\n\nThe configuration for Mockaco can be easily customized using the appsettings*.json fi"
  },
  {
    "path": "website/docs/generator/_category_.json",
    "chars": 44,
    "preview": "{\n  \"label\": \"Generator\",\n  \"position\": 6\n}\n"
  },
  {
    "path": "website/docs/generator/index.md",
    "chars": 550,
    "preview": "# Generator\n\nThis feature allows to generate mock templates based on provided specification eg. OpenApi, simply using `g"
  },
  {
    "path": "website/docs/guides/_category_.json",
    "chars": 171,
    "preview": "{\n  \"label\": \"Guides\",\n  \"position\": 100,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"5 minutes to le"
  },
  {
    "path": "website/docs/guides/mocking-raw.md",
    "chars": 2768,
    "preview": "# Mocking binary/raw responses\n\nMockaco is able to respond raw file contents, so it's possible to return a file, image o"
  },
  {
    "path": "website/docs/guides/mocking-stateful.md",
    "chars": 3487,
    "preview": "# Stateful mocks\n\nMockaco can persist states to allow mocking multiple behaviors for the same endpoint.\nThese states are"
  },
  {
    "path": "website/docs/guides/mocking-xml.md",
    "chars": 2251,
    "preview": "# Mocking XML responses\n\nMockaco is able to parse XML request and make its elements available to be used in the response"
  },
  {
    "path": "website/docs/health-checks/_category_.json",
    "chars": 48,
    "preview": "{\n  \"label\": \"Health Checks\",\n  \"position\": 8\n}\n"
  },
  {
    "path": "website/docs/health-checks/index.md",
    "chars": 3484,
    "preview": "# Health Checks\n\nHealth checks are often useful when Mockaco container is being used.\n\n## `/_mockaco/health`\n\nTo determi"
  },
  {
    "path": "website/docs/quick-start/_category_.json",
    "chars": 173,
    "preview": "{\n  \"label\": \"Quick Start\",\n  \"position\": 2,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Mockaco is a"
  },
  {
    "path": "website/docs/quick-start/create-mock.md",
    "chars": 449,
    "preview": "---\nsidebar_position: 2\n---\n\n# Create a mock\n\nCreate a file named `ping-pong.json` under `Mocks` folder.\n\n```json\n{\n  \"r"
  },
  {
    "path": "website/docs/quick-start/install-run.md",
    "chars": 1706,
    "preview": "---\nsidebar_position: 1\n---\n\n# Install and run\n\nChoose your favorite way to install Mockaco locally or in your server.\n\n"
  },
  {
    "path": "website/docs/quick-start/test-mock.md",
    "chars": 342,
    "preview": "# Test\n\nSend a request and get the mocked response.\nAccess [http://localhost:5000/ping](http://localhost:5000/ping) or c"
  },
  {
    "path": "website/docs/reference-scripting/_category_.json",
    "chars": 54,
    "preview": "{\n  \"label\": \"Scripting Reference\",\n  \"position\": 3\n}\n"
  },
  {
    "path": "website/docs/reference-scripting/faker.md",
    "chars": 2673,
    "preview": "# Faker\n\n## Basic usage\n\nA `Faker` facade object is available to generate fake data within a script.\n\n```\n{\n  \"request\":"
  },
  {
    "path": "website/docs/reference-scripting/global.md",
    "chars": 1584,
    "preview": "# Global\n\nThe Global object is a global variable that can be used to store variables that are shared between all mock re"
  },
  {
    "path": "website/docs/reference-scripting/index.md",
    "chars": 3351,
    "preview": "# Scripting\n\nEvery part of the mock file is scriptable, so you can add code to programmatically generate parts of the te"
  },
  {
    "path": "website/docs/reference-scripting/request.md",
    "chars": 4619,
    "preview": "# Request\n\nThe Request object has the following properties:\n\n## Url\n\nAn instance of [`Uri`](https://learn.microsoft.com/"
  },
  {
    "path": "website/docs/reference-scripting/response.md",
    "chars": 591,
    "preview": "# Response\n\nThe Response object is accessible **after** the mock is generated. This object contains response that was se"
  },
  {
    "path": "website/docs/reference-template/_category_.json",
    "chars": 156,
    "preview": "{\n  \"label\": \"Mock Template Reference\",\n  \"position\": 3,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \""
  },
  {
    "path": "website/docs/reference-template/callback/_category_.json",
    "chars": 184,
    "preview": "{\n  \"label\": \"callback object\",\n  \"position\": 3,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Prepare "
  },
  {
    "path": "website/docs/reference-template/callback/body-attribute.md",
    "chars": 597,
    "preview": "# body attribute\n\nSets the content to be sent to another server.\n\nIf omitted, empty or null, defaults to empty.\n\n## Exam"
  },
  {
    "path": "website/docs/reference-template/callback/delay-attribute.md",
    "chars": 588,
    "preview": "# delay attribute\n\nWaits for a specific amount of time in milliseconds before sending the callback.\nIf omitted, empty or"
  },
  {
    "path": "website/docs/reference-template/callback/headers-attribute.md",
    "chars": 300,
    "preview": "# headers attribute\n\nAllow to set headers of the callback request.\n\n## Example\n\n```json\n{\n  \"request\": {\n\t\"method\": \"GET"
  },
  {
    "path": "website/docs/reference-template/callback/method-attribute.md",
    "chars": 390,
    "preview": "# method attribute\n\nDefine which [HTTP request method](https://developer.mozilla.org/docs/Web/HTTP/Methods) will be used"
  },
  {
    "path": "website/docs/reference-template/callback/timeout-attribute.md",
    "chars": 420,
    "preview": "# timeout attribute\n\nSpecify an amount of time in milliseconds to wait for the callback request response.\n\nDefault: `500"
  },
  {
    "path": "website/docs/reference-template/callback/url-attribute.md",
    "chars": 84,
    "preview": "# url attribute\n\nSet the callback target absolute URL. This attribute is required.\n\n"
  },
  {
    "path": "website/docs/reference-template/request/_category_.json",
    "chars": 288,
    "preview": "{\n  \"label\": \"request object\",\n  \"position\": 1,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Use this "
  },
  {
    "path": "website/docs/reference-template/request/condition-attribute.md",
    "chars": 974,
    "preview": "---\nsidebar_position: 3\n---\n# condition attribute\n\nAny condition that evaluates to ```true``` will return the response. "
  },
  {
    "path": "website/docs/reference-template/request/method-attribute.md",
    "chars": 341,
    "preview": "---\nsidebar_position: 1\n---\n# method attribute\n\nAny request with the matching HTTP method will return the response. Supp"
  },
  {
    "path": "website/docs/reference-template/request/route-attribute.md",
    "chars": 341,
    "preview": "---\nsidebar_position: 2\n---\n# route attribute\n\nAny request with the matching route will return the response. Any AspNet "
  },
  {
    "path": "website/docs/reference-template/response/_category_.json",
    "chars": 148,
    "preview": "{\n  \"label\": \"response object\",\n  \"position\": 2,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Compose "
  },
  {
    "path": "website/docs/reference-template/response/body-attribute.md",
    "chars": 495,
    "preview": "# body attribute\n\nSets the HTTP response body.\n\nIf omitted, empty or null, defaults to empty.\n\nThe ```Content-Type``` he"
  },
  {
    "path": "website/docs/reference-template/response/delay-attribute.md",
    "chars": 274,
    "preview": "# delay attribute\n\nDefines a minimum response time in milliseconds. Useful to produce an artificial timeout.\n\nIf omitted"
  },
  {
    "path": "website/docs/reference-template/response/file-attribute.md",
    "chars": 425,
    "preview": "# file attribute\n\nAllow to define a file to be returned in body\n\n## Example\n\n```json\n{\n  \"request\": {\n    \"method\": \"GET"
  },
  {
    "path": "website/docs/reference-template/response/headers-attribute.md",
    "chars": 192,
    "preview": "# headers attribute\n\nSets any HTTP response headers.\n\n## Example\n```json\n{\n  \"request\": {\n\t\"method\": \"GET\"\n  },\n  \"respo"
  },
  {
    "path": "website/docs/reference-template/response/indented-attribute.md",
    "chars": 595,
    "preview": "# indented attribute\n\nSets the response body indentation for some structured content-types. If ommited, defaults to ```t"
  },
  {
    "path": "website/docs/reference-template/response/status-attribute.md",
    "chars": 453,
    "preview": "# status attribute\n\nSets the HTTP status code for the response. Can be a text or numeric value, as defined in [System.Ne"
  }
]

// ... and 15 more files (download for full content)

About this extraction

This page contains the full source code of the natenho/Mockaco GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 215 files (312.2 KB), approximately 79.1k tokens, and a symbol index with 443 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!