{"id":42486017,"url":"https://github.com/aemonge/green-tomato","last_synced_at":"2026-01-28T11:28:23.526Z","repository":{"id":57253941,"uuid":"67146229","full_name":"aemonge/green-tomato","owner":"aemonge","description":"A sandbox and mock server that automatically records mocks by a reverse proxy. It can be used as a API cache","archived":false,"fork":false,"pushed_at":"2020-06-04T09:21:30.000Z","size":39,"stargazers_count":9,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-20T00:08:00.951Z","etag":null,"topics":["api","cache","javascript","library","mock","nodejs","proxy","sandbox"],"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/aemonge.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-09-01T16:02:43.000Z","updated_at":"2021-12-21T16:13:33.000Z","dependencies_parsed_at":"2022-08-31T08:21:35.983Z","dependency_job_id":null,"html_url":"https://github.com/aemonge/green-tomato","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/aemonge/green-tomato","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aemonge%2Fgreen-tomato","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aemonge%2Fgreen-tomato/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aemonge%2Fgreen-tomato/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aemonge%2Fgreen-tomato/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aemonge","download_url":"https://codeload.github.com/aemonge/green-tomato/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aemonge%2Fgreen-tomato/sbom","scorecard":{"id":168862,"data":{"date":"2025-08-11","repo":{"name":"github.com/aemonge/green-tomato","commit":"1509b163a965c014c03435cc15517f4aa3d5c4df"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"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":"Code-Review","score":0,"reason":"Found 1/29 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":"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":"Dangerous-Workflow","score":-1,"reason":"no workflows found","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":-1,"reason":"No tokens found","details":null,"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":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"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":"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":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"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":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"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":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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":"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":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 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"}}]},"last_synced_at":"2025-08-16T15:47:53.482Z","repository_id":57253941,"created_at":"2025-08-16T15:47:53.482Z","updated_at":"2025-08-16T15:47:53.482Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28845088,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T10:53:21.605Z","status":"ssl_error","status_checked_at":"2026-01-28T10:53:20.789Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["api","cache","javascript","library","mock","nodejs","proxy","sandbox"],"created_at":"2026-01-28T11:28:22.863Z","updated_at":"2026-01-28T11:28:23.519Z","avatar_url":"https://github.com/aemonge.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# green-tomato\nA sandbox (mock server), that allows the user to **record** the mocks from the APIs, avoiding the struggle of the\ncreation of the mock data. It uses mongoDB to store such data, and also to manually add the mock in the following\nformat.\n\n```json\n{\n  \"url\": \"/get\",\n  \"method\": \"GET\",\n  \"headers\": null,\n  \"body\": null,\n  \"responseData\": \"can be plain text, or a json object\",\n  \"responseStatusCode\": { \"$numberInt\": \"200\" },\n  \"timeStamp\": { \"$date\": { \"$numberLong\": \"1585741795795\" } }\n}\n```\n\n## Features\n* Run it as a server and/or locally.\n* Record the mocks automatically from a real request to the server.\n* Respond custom headers and HTTP errors.\n* Supports different sessions by changing the scheme name.\n\n## Dependencies\n\n* https://www.mongodb.com/\n* https://nodejs.org/en/\n\n## Install\n\n`npm install green-tomato`\n\n## Usage\nUse it from nodejs, if you want to use it from a CLI (command line interface) I strongly suggest the following three\nlibraries:\n  * [vorpal](http://vorpal.js.org/)\n  * [commander](https://github.com/tj/commander.js)\n  * [Web-CLI](https://github.com/M1T0zd/Web-CLI#readme)\n\n#### Import and example\n\n```javascript\nvar greenTomato = require('./green-tomato.js');\n\n  greenTomato.serve({\n    useRecords: false,\n    proxyHost: 'https://httpbin.org',\n    port: 5000,\n    mongoSchema: 'default',\n    //searchIgnore: 'path/to/ignore/file',\n    //logLevel: 'quiet',\n    //delay: 0,\n    //regexp: null,\n    //filter: './command'\n  });\n```\n\n## Options\n\n* *useRecords (Boolean)*: Used switch between modes. If true then green-tomato won't return nor request the proxy-host server, instead\n    it will answer based on the current cache build. If false it will forward the request to the proxy-host server and\n    store the answer in the cached database.\n\n* *proxyHost (String):* The target host to create the reverse proxy to.\n\n* *searchIgnore (String):* [only on useRecords mode] A JSON file that will include properties from it to ignore\n    searching in the cache to be more flexible. So if you don't mind the ID of the body request from your cache, you\n    would include the following.\n\n    **ignoreFile.json**\n    ```json\n    {\n      \"body\": {\n        \"id\": \"ignore\"\n      }\n    }\n    ```\n\n    _* you can also set to \"optional\" instead of \"ignore\" to peform two searches, one with the property and another\n    without it. So if by searching with the optional property (ex. :type) no results are found, green-tomato will try\n    another search without the optional property before returnig a server error (418)._\n\n    **ignoreFile.json**\n    ```json\n    {\n      \"body\": {\n        \"id\": \"ignore\",\n        \"type\": \"optional\"\n      }\n    }\n    ```\n\n* *logLevel (String):* Used to determine the amount of information to show in the console. From nothign (\"*quiet*\" or\n  *null*) to only the errors in requests (\"*error*\") which can be the error from the server, those marked as error from\n  the error filter or any search that didn't found any result. And finally the log lever can be\n  (\"verbose\") logging all request and searches.\n\n* *port (Number):* Set the :port number to use for the reverse proxy server at localhost, by default it will use :5000\n\n* *delay (Milliseconds):* [only on useRecords mode] Set time in milliseconds to delay the answer from the cache mode,\nusefull to test timeouts.\n\n* *mongoSchema (String):* The collection to save the cache, used to save different scenarios. By default [default]\n\n* *regexp (Object):* [only on NOT useRecords mode] A regexp (javascript) to search and replace in the URL.\n  * regexp.search (RegExp). The regular expresion to be passed to ULR.replace(*regexp.serach*, regexp.replace).\n  * regexp.replace (String). The susbtitution string to be passed to ULR.replace(regexp.serach, *regexp.replace*).\n\n* *filter (bin):* [only on useRecords mode] A command that takes as an argument the response from the server, and if returns a successful exit code(0) it will store the response on the cache database. Example:\n  ```javascript\n    // -------\n      filter: './userIdFilter.js'\n    // -------\n  ```\n\n  **userIdFilter.js**\n    ```javascript\n    #!/usr/bin/env node\n\n    var response = JSON.parse(process.argv[2]); // Parse the response as JSON with node ;)\n\n    if (response.userId  === 5) {\n      process.exit(0); // This will be included in the cache databases\n    } else {\n      process.exit(1); // This returns error, so green-tomato know that for the current request skip it from storing it.\n    }\n    ```\n\n\n## Simple recipe *commander*, command line interface\n\n```bash\n  npm install green-tomato commander\n  touch index.js\n```\n\nEdit the file **index.js**, and include:\n\n```javascript\n  const Program = require('commander');\n  const { GreenTomato } = require('green-tomato');\n\n  Program\n    .option('-f, --use-records', '')\n    .parse(process.argv);\n\n  let greenTomato = new GreenTomato({\n    useRecords: Program.useRecords,\n    proxyHost: 'https://httpbin.org',\n    logLevel: 'error',\n    port: '5000',\n    mongoSchema: 'default',\n  });\n```\n\n```bash\n  $ node index.js # to start recording\n  $ node index.js -f # to use records\n```\n\n## Simple recipe *webCli*, web command line interface\n\n```bash\n  npm install green-tomato zd-webcli\n  touch index.js\n```\n\nEdit the file **index.js**, and include:\n\n```javascript\n  const webCLI = require('zd-webcli');\n  const { GreenTomato } = require('green-tomato');\n\n  let greenTomato = new GreenTomato({\n    useRecords: false,\n    port: 8090,\n    logLevel: 'error',\n    mongoSchema: 'default'\n  });\n  webCLI.setPassword(\"1234\"); //Set the password.\n  webCLI.setPort(8080); //Set the port.\n\n  webCLI.interpreter((command, args) =\u003e {\n    switch(command) {\n      case 'start':\n        greenTomato.start();\n        break;\n      case 'restart':\n        greenTomato.restart();\n        break;\n      case 'stop':\n        greenTomato.stop();\n        break;\n    }\n  });\n  webCLI.start(); //Start! (Do at the very end!)\n```\n\n```bash\n  $ node index.js\n```\n\nThen open a browser in http://localhost:8080\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faemonge%2Fgreen-tomato","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faemonge%2Fgreen-tomato","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faemonge%2Fgreen-tomato/lists"}