{"id":24186493,"url":"https://github.com/hector-js/stub-backend","last_synced_at":"2025-09-21T10:31:47.719Z","repository":{"id":44567485,"uuid":"135146698","full_name":"hector-js/stub-backend","owner":"hector-js","description":"The aim of this project is to make the life easier stubbing the backend building different responses with authentication and error responses. ","archived":false,"fork":false,"pushed_at":"2024-10-12T22:05:09.000Z","size":1944,"stargazers_count":7,"open_issues_count":13,"forks_count":5,"subscribers_count":1,"default_branch":"development","last_synced_at":"2025-09-21T00:39:13.104Z","etag":null,"topics":["30","30-seconds","cli-command","express","frontend","integration-testing","js","mock","stub","stub-backend"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hector-js.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-28T10:33:45.000Z","updated_at":"2025-08-18T08:39:10.000Z","dependencies_parsed_at":"2023-02-17T12:31:01.992Z","dependency_job_id":"b880c39d-e70b-4840-83d6-de78a7f5be52","html_url":"https://github.com/hector-js/stub-backend","commit_stats":{"total_commits":570,"total_committers":6,"mean_commits":95.0,"dds":0.0368421052631579,"last_synced_commit":"2f7114ec1842cbae16c0db5842eca22da9cae680"},"previous_names":[],"tags_count":179,"template":false,"template_full_name":null,"purl":"pkg:github/hector-js/stub-backend","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hector-js%2Fstub-backend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hector-js%2Fstub-backend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hector-js%2Fstub-backend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hector-js%2Fstub-backend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hector-js","download_url":"https://codeload.github.com/hector-js/stub-backend/tar.gz/refs/heads/development","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hector-js%2Fstub-backend/sbom","scorecard":{"id":459390,"data":{"date":"2025-08-11","repo":{"name":"github.com/hector-js/stub-backend","commit":"ae003b42c715d4e13039c2e8c52b2a2fc126b9c7"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.3,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Security-Policy","score":4,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Warn: no linked content found","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql-analysis.yml:28","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql-analysis.yml:29","Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1","Warn: no topLevel permission defined: .github/workflows/coverage.yml:1","Warn: no topLevel permission defined: .github/workflows/nodejs.yml:1","Warn: no topLevel permission defined: .github/workflows/quality-code.yml:1","Warn: no topLevel permission defined: .github/workflows/unit-tests.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":2,"reason":"dependency not pinned by hash detected -- score normalized to 2","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/codeql-analysis.yml/development?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/codeql-analysis.yml/development?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/codeql-analysis.yml/development?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:71: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/codeql-analysis.yml/development?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/coverage.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/coverage.yml/development?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/coverage.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/coverage.yml/development?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/nodejs.yml/development?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/nodejs.yml/development?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/quality-code.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/quality-code.yml/development?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/quality-code.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/quality-code.yml/development?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/unit-tests.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/unit-tests.yml/development?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/unit-tests.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/hector-js/stub-backend/unit-tests.yml/development?enable=pin","Warn: npmCommand not pinned by hash: scripts/test-all.sh:4","Warn: npmCommand not pinned by hash: .github/workflows/nodejs.yml:52","Info:   0 out of  12 GitHub-owned GitHubAction dependencies pinned","Info:   5 out of   7 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'development'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":7,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 0 commits out of 1 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"18 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-rv95-896h-c2vc","Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-75v8-2h7p-7m2m","Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55","Warn: Project is vulnerable to: GHSA-76c9-3jph-rj3q","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-76p7-773f-r4q5","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T10:41:36.189Z","repository_id":44567485,"created_at":"2025-08-19T10:41:36.189Z","updated_at":"2025-08-19T10:41:36.189Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276229019,"owners_count":25606938,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-21T02:00:07.055Z","response_time":72,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["30","30-seconds","cli-command","express","frontend","integration-testing","js","mock","stub","stub-backend"],"created_at":"2025-01-13T12:35:51.479Z","updated_at":"2025-09-21T10:31:47.422Z","avatar_url":"https://github.com/hector-js.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @hectorjs/stub-backend\n\n![](https://github.com/hector-js/stub-backend/workflows/%40hectorjs%2Fstub%2Dbackend/badge.svg)\n - ![](https://github.com/hector-js/stub-backend/workflows/eslint%2Dconfig%2Dgoogle/badge.svg) ![](https://github.com/hector-js/stub-backend/workflows/Unit%20tests/badge.svg) ![](https://github.com/hector-js/stub-backend/workflows/Coverage/badge.svg) [![codecov](https://codecov.io/gh/hector-js/stub-backend/branch/development/graph/badge.svg)](https://codecov.io/gh/hector-js/stub-backend)\n - ![](https://img.shields.io/npm/v/@hectorjs/stub-backend?label=version\u0026logo=npm) ![](https://img.shields.io/npm/dt/@hectorjs/stub-backend?logo=npm\u0026logoColor=blue) ![](https://img.shields.io/github/last-commit/hector-js/stub-backend?logo=github)\n\n [Releases documentation](https://github.com/hector-js/stub-backend/releases)\n\n# Description\n\nThe aim of this project is to mock the backend services based on a *JSON* configuration. You don't need to do anything programmatically.\n\nThis library gives you the chance to focus in your code **reducing** the amount of work mocking the dependencies. :smile:\n\n# hjs-cli\n\nThere is a command line to generate default scenarios using GET, POST or PUT methods, among others ones.\n\nI suggest you to have a look and give it a try. It will reduce the time to mock the services, which is one of the main goals of this library.\n\nHave a look [@hectorjs/stub-cli](https://www.npmjs.com/package/@hectorjs/stub-cli).\n\n# Installation \n```\nnpm i @hectorjs/stub-backend --save-dev\n```\n## Set hjs command \n:warning: _(this step is not necessary if you have the cli globally installed)_\n\nInclude _hjs_ command in your _package.json_ as a script:\n\n```json\n\"scripts\":{\n  \"hjs\":\"hjs\"\n}\n```\n\n_Note:_ You can check it executing ```npm run hjs -- --version``` in your terminal.\n\n# Structure\n## Packages\nCreate a folder named _\\_hjs_ in the package root directory. Under that folder, create a _resources_ folder and add a couple of json files, which you can name as you wish. You can create subfolders under resources as well.\n\n```\n package.json\n _hjs\n |\n  -resources\n   |\n    - *.json\n    - *.json\n    - subfolder\n      |\n       - *.json\n       - *.json\n```\n## Files structure \nEach file must contain a json object. The first key indicates the method of the request and it must have a \"_\" as a prefix. For example:\n\n```json\n{\n  \"_get\":{        \n  },\n  \"_post\":{       \n  }    \n}\n\n```\n_Methods:_ _get, _head, _post, _put, _delete, _options, _trace, _patch.\n\n## Path level\n\nThe next level indicates the endpoint to call. The path is written as the following examples:\n\n  - /customers/names\n  - /customers/{id}/name\n  - /countries/{id}/product\n  - /countries/{id}/population?town={param1}\u0026postcode={param2}\n\n    ```json\n    {\n      \"_[method]\":{\n         \"/customers/names\":[\n           {}\n         ],\n         \"/customers/{id}/name\":[\n           {}\n         ],\n         \"/countries/{id}/product\":[\n           {}\n         ],\n         \"/countries/{id}/population?town={param1}\u0026postcode={param2}\":[\n           {}\n         ]\n      }\n    }\n    ```\n_NOTE_: id, param1 or param2 can be named as you want. However, they must be unique.\n\n## Scenarios\n\nThis level indicates possible scenarios based on different parameters.\n\nIndex:\n - [_req](#_req)\n - [_res](#_res)\n\n\nEach scenario contains two sections **_req** (request) and **_res** (response) where we place the properties in relation to the request and response.\n\n:warning: Both levels are **mandatory** in each scenario. Even if you don't want to add anything in the request, you must add an empty __req_.\n\n## _req\n\nBasically, the scenario which is going to be selected to provide the response is the one which has more matches in the _req section with the real request.\n\n```json\n\"/customers/{id1}/data/{id2}\" : [\n  {\n    \"_req\":{\n    }\n  },\n  {\n    \"_req\":{\n    }\n  }\n]\n```\n\nYou can have the following properties for matching the request:\n - [_[id]](#_[id])\n - [_headers](#_headers)\n - [_cookies](#_cookies)\n - [_body](#_body)\n - [_bodyPaths](#_bodyPaths)\n - [_excludeBodyFields](#_excludeBodyFields)\n\n### _[id]\n\nIdentifiers of a path. For example, given a path ```/customers/{id1}/data/{id2}```, it should be structured as follows:\n\n```json\n\"/customers/{id1}/data/{id2}\" : [\n  {\n    \"_req\":{\n      \"_id1\": \"chris\",\n      \"_id2\": \"1\"\n    }\n  },\n  {\n    \"_req\":{\n      \"_id1\": \"Fran\",\n      \"_id2\": \"2\"\n    }\n  }\n]\n```\n\nIt will choose the first scenario when _id1_ is Chris and _id2_ is 1 and the second one when _id1_ is Fran and _id2_ is 2.\n\n_cli_ ```hjs generate get customers/{id1}/data/{id2}```\n\n_NOTE:_ If you include ```*``` as a value, it will work as a wildcard.\n\nFor example, given the example above when the request is ```/customers/chris/data/*```, it will choose the first scenario.\n\n### _headers\n\nThere are two different ways to match by headers:\n\n#### Match by key\n\nIt is an array of header keys. Basically, it will match if the request contains all the headers in the array.\n\n```json\n\"/customers/{id}/data\" : [\n  {\n    \"_req\":{\n      \"_headers\": [\"authorization\", \"client_Id\"]\n    }\n  }\n]\n```\n_cli_ ```hjs generate get customers/{id}/data --headers authorization,client_Id```\n\n#### Match by key or match by value\n\nHeader can match key or values for specific fields also where required.\n\n```json\n\"/customers/{id}/data\" : [\n  {\n    \"_req\":{\n      \"_headers\": [\"authorization\", {\"client_Id\": \"expected_value\"}]\n    }\n  }\n]\n```\n\n#### Match by key and value\n\nIt is an array of objects. The key is the header name and the value is the header value. You can see it in the next example:\n\n\n```json\n\"/customers/{id}/data\" : [\n  {\n    \"_req\":{\n      \"_headers\": {\n        \"authorization\":\"1234\",\n        \"client_Id\":\"121\"\n        }\n    }\n  }\n]\n```\n\n_cli_ ```hjs generate get customers/{id}/data --headers authorization,client_Id```\n\nSet the key value headers manually.\n\n_NOTE:_ If the scenario does not contain any headers section, the service won't check anything. Capital letters are not allow in headers section.\n\n#### Content-type\n\nBy default all the requests are based on json.\n\nIf you include in your header the following options:\n\n1. multipart/form-data \n  \n  The values keyName=ValueName will be matching in the body section like:\n\n  ```\n  {\n    _body:{\n      [keyName]:[ValueName]\n    }  \n  }\n  ```\n\n2. application/x-www-form-urlencoded\n  \n  The values keyName=ValueName will be matching in the body section like:\n\n  ```\n  {\n    _body:{\n      [keyName]:[ValueName]\n    }  \n  }\n  ```\n\n### _cookies\n\nThere are two different ways to match the cookies:\n\n#### Match by key\n\nIt is an array of cookies keys. Basically, it will match if the request contains all the cookies in the array.\n\n```json\n\"/customers/{id}/data\" : [\n  {\n    \"_req\":{\n      \"_cookies\": [\"Universal\", \"sec\"]\n    }\n  }\n]\n```\n\n_cli_: ```hjs generate get customers/{id}/data --cookies Universal,sec```\n\n#### Match by key-value\n\nIt is an array of objects. The key is the header name and the value is the header value. You can see in the next example:\n\n```json\n\"/customers/{id}/data\" : [\n  {\n    \"_req\": {\n      \"_cookies\": {\n        \"Universal\":\"123\", \n        \"sec\":\"1232\"\n        }\n    }\n  }\n]\n```\n\n_NOTE:_ If the scenario does not contain any cookies section, the service won't check anything.\n\n\n_cli_ ```hjs generate get customers/{id}/data --cookies authorization,client_Id```\n\nSet the key value cookies manually.\n\n_NOTE:_ If the scenario does not contain any cookies section, the service won't check anything.\n\n### _body\n\nYou might want to match the body for some methods like post, put or delete. **_body** object is the request body  for a specific scenario. It will check the entire object.\n\n```json\n\"/customers/{id}/data\" : [\n  {\n    \"_req\": {\n      \"_body\": {\n        \"dummyRequestBody1\": \"anyValue\"   \n      }\n    }\n    \"_description\": \"secure scenario given an authorization header\"\n  }\n]\n```\n\n_Note:_ If any field is missed, the scenario will not be matched.\n\n### _bodyPaths\n\nInstead of matching the entire body of a request, you can verify verify just a specific fields or objects using __bodyPaths_.\n\n_bodyPaths_ is a key value object where the _key_ is the jsonPath and the _value_ is the object to match.\n\nExample:\n\n```json\n\"/customers/{id}/data\" : [\n  {\n    \"_req\": {\n      \"_bodyPaths\": {\n        \"$.heroes\": { \"name\": \"superman\"}, \n        \"$.cities[0].name\": \"madrid\"\n      }\n    },\n    \"_res\":{\n    },\n    \"_description\":\"secure scenario given an authorization header\"\n  }\n]\n```\n\n_bodyPaths can be an array also as an option to validate a field or value.\n\n```json\n\"/customers/{id}/data\" : [\n  {\n    \"_req\": {\n      \"_bodyPaths\": [\n        \"$.heroes\": { \"name\": \"superman\"}, \n        \"$.cities[0].name\"\n      ]\n    },\n    \"_res\":{\n    },\n    \"_description\":\"secure scenario given an authorization header\"\n  }\n]\n```\n\nAlso, you can include a regex to check different values. Example:\n```json\n\"/customers/{id}/data\" : [\n  {\n    \"_req\": {\n      \"_bodyPaths\": {\n        \"$.id\": \"^[v].*[3]$\"\n      }\n    },\n    \"_res\":{\n    }\n  }\n]\n```\nAbove expresion will check id which starts with v and ends with 3\n\n\n_NOTE:_ bodyPaths and body section can not be at the same time.\n\n### _excludeBodyFields\n\nWhenever you need to exclude the comparation of some fields (timestamps for example) or objects from the __body_ or _bodyPaths_,  You can do it adding an array of json paths  (you can exlude multiple fields or objects).\n\n```json\n\"_excludeBodyFields\": [ \"$.value1.value2[0]\", \"$.value3\"]\n```\n\n_Note:_ If you have any doubt about how to do the path, you can have a look to [jsonPath libray](https://www.npmjs.com/package/jsonpath) which is used in the project.\n\n_Note:_ The library will not exclude any field or object if __excludeBodyFields_ is not added.\n\n## _res\n\nThis section create a response when a scenario is matched.\n\n```json\n\"/customers/{id1}/data/{id2}\" : [\n  {\n    \"_res\":{\n    }\n  },\n  {\n    \"_res\":{\n    }\n  }\n]\n```\n\nYou can have the following properties in the response:\n\n - [_status](#_status)\n - [_headers](#_headers)\n - [_cookies](#_cookies)\n - [_delay](#_delay)\n - [_body](#_body)\n\n### _status\n\nYou can set your own status.\n\n```json\n\"/customers/{id1}/data/{id2}\" : [\n  {\n    \"_res\":{\n      \"_status\": 400\n    }\n  },\n  {\n    \"_res\":{\n      \"_status\": 404\n    }\n  }\n]\n```\n\n_cli_: ```hjs generate get customers/{id}/data/{id2} --status 404```\n\n_NOTE:_ if _status doesn't exist, it will return 200.\n\n### _headers\n\nYou have the option to set headers in the response just by key or key-value.\n\n#### by key\n```json\n\"/customers/{id1}/data/{id2}\" : [\n  {\n    \"_res\":{\n      \"_headers\": [\"key-header-1\", \"key-header-2\"]\n    }\n  }\n]\n```\n\n_NOTE:_ the value of each key will be generated with default values.\n\n#### by key-value\n```json\n\"/customers/{id1}/data/{id2}\" : [\n  {\n    \"_res\":{\n      \"_headers\": {\n        \"key-header-1\": \"custom-value-1\",\n        \"key-header-2\": \"custom-value-2\"\n      }\n    }\n  }\n]\n```\n\n### _cookies\n\nYou have the option to set cookies in the response just by key or key-value.\n\n#### by key\n```json\n\"/customers/{id1}/data/{id2}\" : [\n  {\n    \"_res\":{\n      \"_cookies\": [\"key-cookie-1\", \"key-cookie-2\"]\n    }\n  }\n]\n```\n\n_NOTE:_ the value of each key will be generated with default values.\n\n#### by key-value\n```json\n\"/customers/{id1}/data/{id2}\" : [\n  {\n    \"_res\":{\n      \"_cookies\": {\n        \"key-cookie-1\": \"custom-value-1\",\n        \"key-cookie-2\": \"custom-value-2\"\n      }\n    }\n  }\n]\n```\n\n### _delay\n\nIt is adding a delay in milliseconds to the response.\n\n```json\n\"/customers/{id1}/data/{id2}\" : [\n  {\n    \"_res\":{\n      \"_delay\": 10000\n    }\n  }\n]\n```\n\n_cli_: ```hjs generate get customers/{id}/data --delay 1000```\n\n### _body\n\nThis section contains the response for a given request.\n\n```json\n\"/customers/{id1}/data/{id2}\" : [\n  {\n    \"_res\":{\n      \"_body\": {\n        \"dummyResponse1\": \"anyValue\"\n      }\n    }\n  },\n  {\n    \"_res\":{\n      \"_body\": {\n        \"dummyResponse2\": \"anyValue\"\n      }\n    }\n  }\n]\n```\n\n## _description\n\nBrief explanation about the scenario.\n\n```json\n\"/customers/{id}/data\" : [\n  {\n    \"_req\": {\n      \n    },\n    \"_res\":{\n\n    },\n    \"_description\":\"secure scenario given an authorization header\"\n  }\n]\n```\n\n_cli_: ```hjs generate get customers/{id}/data --description \"Hello world\"```\n\n# Example\n\nBelow, we have a example:\n\n```json\n{\n  \"_get\": {\n    \"/stories/{id}/person$\": [\n      {\n        \"_req\":{\n          \"_id\": \"Nathan\",\n          \"_headers\": []\n        },\n        \"_res\":{\n          \"_body\": {\n            \"name\": \"Nathan\"\n          }\n        },\n        \"_description\": \"Get person details related to  Nathan without authentication\"\n      },\n      {\n        \"_req\":{\n          \"_id\": \"Lucas\",\n          \"_headers\": []\n        },\n        \"_res\":{\n          \"_status\": 304,\n          \"_body\": {\n            \"name\": \"Nathan\"\n          }\n        },\n        \"_description\": \"There won't be any response    because the status is 304\"\n      },\n      {\n        \"_req\":{\n          \"_id\": \"mark\",\n          \"_headers\": [\"authorization\"],\n          \"_cookies\": []\n        },\n        \"_res\":{\n          \"_body\": {\n            \"name\": \"Mark\"\n          }\n        },\n        \"_description\": \"Get person details related to Mark     with authentication\"\n      }\n    ]\n  },\n  \"_post\" :{\n      \"/stories/{id}/budget\": [\n        {\n          \"_req\":{\n            \"_id\": \"Nathan\",\n            \"_headers\": [\"Client_id\"],\n            \"_cookies\": [\n              \"session-id\",\n              \"key-id\"\n            ],\n            \"_body\": {\n              \"anyData\": \"anyData\"\n            },\n          },\n          \"_res\":{\n            \"_body\": {\n              \"name\": \"Nathan\"\n            }\n          },\n          \"_description\": \"Get budget details related to  Nathan with authentication\"\n        }\n      ]\n  }\n}\n```\n\nIf you want to test it, copy the previous example and paste it in one of the json files. Then execute the following command:\n\n```sh\nnode .\\\\node_modules\\\\@hectorjs\\\\stub-backend\\\\lib\\\\app.js\n```\nor with _cli_\n\n```sh\nhjs start\n```\n\nThe service will be running in the port *3005* waiting for a request.\n\nMake a request:\n\n```sh\ncurl http://localhost:3005/stories/nathan/person\n```\n\nThe response will be like this:\n\n```json\n{\n    \"name\": \"Nathan\"\n}\n```\n\n# Advance options\n\n- [Xml](#Xml)\n- [Avoid delays](#Avoid\u0026nbsp;Delays)\n- [Banner](#Banner)\n- [Retry opts](#Retry\u0026nbsp;opts)\n- [Same request different response](#Same\u0026nbsp;request\u0026nbsp;different\u0026nbsp;response)\n- [Config file](#Config\u0026nbsp;file)\n\n## Xml\n\nThis section is in progress. At this moment, the user can response a xml setting the **_xml** flag to true like the following scenario:\n\n```json\n{\n \"_post\" :{\n    \"/stories/{id}/budget\": [\n      {\n        \"_req\":{\n          \"_id\": \"Nathan\",\n          \"_body\": \"\u003cxml\u003e\u003cbook\u003e\u003ctitle\u003eThe lyon king\u003c/title\u003e\u003c/book\u003e\u003c/xml\u003e\",\n        },\n        \"_res\":{\n          \"_xml\": true,\n          \"_body\": \"\u003cxml\u003e\u003cbook\u003e\u003ctitle\u003eFlash\u003c/title\u003e\u003c/book\u003e\u003c/xml\u003e\"\n        }\n      }\n    ]\n  }\n}\n```\n\n## Avoid Delays\nYou have the option to avoid all the delays. By default, it will execute the mocks with delays, but you can add ```--no_delay``` arg and the application won't add delays.\n\nExample: ```hjs start --no_delay```\n\n## Banner\nYou can use your own banner instead of hectorjs one. You just need to add a file called ```.hjs.banner.js``` in the roor of your project. Have a look to the following example:\n\n```js\nmodule.exports = function(){\n    console.log('\\x1b[32m%s\\x1b[0m', 'My custom message');\n}\n```\n\n_NOTE:_ you can add a config file using the following command:\nFor an existing project:\n  * ```hjs config --banner``` have upper version  0.24.0 hectorjs/stub-cli.\nFor a new mock service:\n  * ```hjs new --banner``` create project with a custom banner.\n\n## Retry opts\n\nA possible scenario including retry options could be:\n\n```json\n{\n  \"_get\": {\n    \"/customers/{id}\": [{\n        \"_req\": {\n          \"_id\": \"2\"\n        },\n        \"_retry\": 2,\n        \"_res\": {\n          \"_body\": {\n            \"any\": \"dummy response\"\n          }\n        },\n        \"_resRetry\": [{\n            \"_body\": {\n              \"any\": \"body for first try\"\n            },\n            \"_headers\": [ \"header for first try\"]\n          },\n          {\n            \"_body\": {\n              \"any\": \"body for second try\"\n            },\n            \"_headers\": [ \"header for second try\"]\n          }]\n      }]\n    }\n}\n```\nWhere ```_retry``` fields means the number of retries for that specific request and ```_resRetry``` will be an array of different responses scenarios.\n\nFor the example, the first request will optain a response:\n\n```json\n{\n  \"_body\": {\n    \"any\": \"dummy response\"\n  }\n}\n```\n2 request:\n```json\n{\n  \"_body\": {\n    \"any\": \"body for first try\"\n  },\n  \"_headers\": [ \"header for first try\"]\n}\n```\n\n3 request: \n```json\n{\n  \"_body\": {\n    \"any\": \"body for second try\"\n  },\n  \"_headers\": [ \"header for second try\"]\n}\n```\n\nIf you make again a request it will start from the beginning as you have achieved the number of retries.\n\n## Same request different response\n\nThere are scenarios where the user wants to provide different responses for the same request. The library provide the following feature to be able to do it.\n\nIt needs to add a custom id in the root of the scenario like the example below:\n\n```json\n{\n  \"_get\": {\n    \"/customers\":[\n      {\n        \"_id\": \"ID_1\",\n        \"_req\":{},\n        \"_res\":{\n          \"_body\": {\n            \"size\":100\n          }\n        }\n      },\n      {\n        \"_id\": \"ID_2\",\n        \"_req\":{},\n        \"_res\":{\n          \"_body\": {\n            \"size\":200\n          }\n        }\n      }\n    ]\n}\n```\nBasically, it requires to tell to the library which id to use before making the request.\n\nThe library expose three endpoints to deal with the id.\n\n- POST \"/__scenario\" body: ```{ id: 'CUSTOM_ID' }```\n  This request sets the id in the library. For the example above, if we want to response the first scenario, we should make the next request before the mock is executed:\n\n  ```curl\n  curl -X POST \\\n  http://localhost:3005/__scenario \\\n  -H 'cache-control: no-cache' \\\n  -H 'content-type: application/json' \\\n  -d '{\n\t  \"id\":\"ID_1\"\n  }'\n  ```\n\n- GET \"/__scenario\" response: ```{ id: 'CUSTOM_ID' }```\n  If we want to know which id is set in the library in that moment, we need to make a a get request. Using the example above:\n\n  ```curl\n  curl -X GET \\\n  http://localhost:3005/__scenario \\\n  ```\n\n- POST \"/__scenario/reset \n  Reset the identifier in the library\n\n  ```curl\n  curl -X POST \\\n  http://localhost:3005/__scenario/reset \\\n  ```\n\n\n## Config file\n\nYou can add your config file in the root of the mock service or in the root of the project. The name of the file must be _.hjs.config.json_\n\nAt this moment, the developer can use the following options:\n\n### Cors Options\n\nYou can add _corsOptions_ as the [cors library](https://www.npmjs.com/package/cors#configuring-cors) is doing. For example:\n\n```json\n{\n  \"corsOptions\":{\n    \"origin\": \"http://your-url.com\",\n    \"optionsSuccessStatus\": 200\n  }\n}\n```\n\n### Logs\n\nYou can include the level of logs fot the mock using [morgan options](https://www.npmjs.com/package/morgan). For example: \n\n```json\n{\n  \"logs\": \":method :url :status :res[content-length] - :response-time ms\"\n}\n```\n\n### Port\n\nExpecify the port. It is 3005 by default.\n\n```json\n{\n  \"port\": 8081\n}\n```\n### UI\n\nExpecify if you want to enable the ui. By default is disabled.\n\n```json\n{\n  \"ui\": {\n    \"enable\": true\n  }\n}\n```\n\n# Compatibility\n\n It requires 1.0.0 or newer versions of @hectorjs/cli.\n\n# Respository\n\nhttps://github.com/hector-js/stub-backend\n\n\nPlease, I am up for feedback and new issues for the respository.\n\nThank you","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhector-js%2Fstub-backend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhector-js%2Fstub-backend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhector-js%2Fstub-backend/lists"}