{"id":22050131,"url":"https://github.com/icapps/tree-house","last_synced_at":"2025-07-15T22:18:38.242Z","repository":{"id":45296935,"uuid":"89916431","full_name":"icapps/tree-house","owner":"icapps","description":"NodeJS utilities and handy helpers extending ExpressJS functionalities","archived":false,"fork":false,"pushed_at":"2024-06-06T14:03:19.000Z","size":848,"stargazers_count":10,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-10T09:06:09.844Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/icapps.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-05-01T10:50:00.000Z","updated_at":"2024-06-06T14:03:23.000Z","dependencies_parsed_at":"2024-06-19T19:08:49.623Z","dependency_job_id":"58bce137-386e-4585-9fee-c1f2bde3f141","html_url":"https://github.com/icapps/tree-house","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/icapps/tree-house","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icapps%2Ftree-house","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icapps%2Ftree-house/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icapps%2Ftree-house/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icapps%2Ftree-house/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/icapps","download_url":"https://codeload.github.com/icapps/tree-house/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icapps%2Ftree-house/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265464418,"owners_count":23770323,"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","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":[],"created_at":"2024-11-30T14:17:58.922Z","updated_at":"2025-07-15T22:18:37.975Z","avatar_url":"https://github.com/icapps.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Treehouse\n\nNodeJS utilities and handy helpers extending ExpressJS functionalities\n\n[![npm version](https://badge.fury.io/js/tree-house.svg)](https://badge.fury.io/js/tree-house)\n[![Dependencies](https://david-dm.org/icapps/tree-house.svg)](https://david-dm.org/icapps/tree-house.svg)\n[![Build Status](https://travis-ci.com/icapps/tree-house.svg?branch=master)](https://travis-ci.com/icapps/tree-house)\n[![Coverage Status](https://coveralls.io/repos/github/icapps/tree-house/badge.svg)](https://coveralls.io/github/icapps/tree-house)\n[![Greenkeeper badge](https://badges.greenkeeper.io/icapps/tree-house.svg)](https://greenkeeper.io/)\n\n## Installation\n\nInstall via npm\n\n```shell\nnpm install tree-house\n```\n\nor via yarn\n\n```shell\nyarn add tree-house\n```\n\n## Usage\n\n```javascript\nconst treehouse = require('tree-house')\n```\n\n```javascript\nimport * as treehouse from 'tree-house'\n```\n\n## Security\n\n### setBasicSecurity(app, route, options)\n\nSet some basic Express security using `cors` and `helmet`.\n\n```javascript\nconst app = express();\n\ntreehouse.setBasicSecurity(app, '*', {\n  cors: {},   // cors options\n  helmet: {}, // helmet options\n})\n```\n\n- [All available helmet options](https://github.com/helmetjs/helmet)\n- [All available cors options](https://github.com/expressjs/cors)\n\n### setBodyParser(app, route, options)\n\nSet a body parser using the `body-parser` module\n\n```javascript\nconst app = express();\n\ntreehouse.setBodyParser(app, '*', {\n  json: {},   // json options\n  raw: {}, // raw options\n  text: {}, // text options\n  urlEncoded: {}, // urlEncoded options\n})\n```\n\n- [All available body parser options](https://github.com/expressjs/body-parser)\n\n### getRateLimiter(options)\n\nGet a rate limiter instance to prevent brute force attacks. This can be used as a middleware in Express.\nAt the moment there is support for a built in-memorystore or Redis. Both use the `express-rate-limit` module.\n\n```javascript\nconst app = express();\n\n// In memory store (development purposes)\nconst globalRateLimiter = treehouse.getRateLimiter({\n  max: 100, // limit each IP to 100 requests per windowMs\n  delayMs: 0 // disable delaying - full speed until the max limit is reached\n  windowMs: 60 * 60 * 1000, // 1 hour window\n  message:\n    \"Too many accounts created from this IP, please try again after an hour\"\n});\n\napp.use('/login', globalRateLimiter, ...);\n\n// Using existing Redis client\ntreehouse.getRateLimiter({\n  redis: {\n    client: existingClient, // All Redis options or 'client' to use an existing client (see rate-limit-redis)\n  },\n});\n```\n\n- [All available Express-rate-limit options](https://github.com/nfriedly/express-rate-limit)\n- [All available Redis options](https://github.com/NodeRedis/node_redis)\n\n## Responder\n\n### handleAsyncFn((req, res, next(optional)) =\u003e { ... })\n\nExpress middleware that wraps and executes a given function with try/catch to avoid unhandled promises within Express.\n\n```javascript\nconst app = express();\n\nfunction getAllUsers(req, res) {\n  //  res.send(users) -\u003e return users...\n  // or\n  // if an unhandled error occurs this will be passed onto the Express error handler instead of raising an UnhandledPromiseRejectionError\n}\n\napp.use('/users', treehouse.handleAsyncFn(getAllUsers));\n```\n\n## Server\n\n### startServer(app, options)\n\nStart an http or https server using an express instance\n\n```javascript\nconst app = express();\n\ntreehouse.startServer(app, {\n  port: 3000,\n  title: 'My app',\n  pre: preFn,       // function to execute before starting server (optional)\n  post: postFn,     // function to execute after starting server (optional) - will contain the http server as first argument\n  https: {          // optional\n    port: 3001,\n    privateKey: 'assets/ssl.key',\n    certificate: 'assets/ssl.cert',\n  },\n  keepAliveTimeout: 60000, // optional\n  headersTimeout: 60000, // optional\n})\n```\n\n## Swagger\n\n### setSwagger(app, route, filePath, options)\n\nServe Swagger UI via the a provided Swagger yaml file OR folder with valid structure and yaml files.\n\n### YAML file implementation\n\n```javascript\nconst app = express();\n\nawait treehouse.setSwagger(app, '/documentation', 'documentation/swagger.yml', {\n  host: 'localhost:3000',\n  schemes: ['http'],\n};\n```\n\n- [All available swagger-ui options](https://github.com/swagger-api/swagger-ui)\n\n### Folder  implementation with valid structure\n\nStructure\n\n```bash\n.\n├── validFolderName\n|   ├── index.yml # contains basic info + definition models\n|   └── routes\n|          ├── route1.yml\n|          └── randomName.yml\n|          ├── ... # more yml files\n```\n\nExample code\n\n```javascript\nconst app = express();\n\ntreehouse.setSwagger(app, '/documentation', 'documentation/validFolderName', {\n  host: 'localhost:3000',\n  schemes: ['http'],\n  concatenate : true, // The property to enable folder functionality\n};\n```\n\n- [All available swagger-ui options](https://github.com/swagger-api/swagger-ui)\n\n## Validator\n\n### validateSchema(schema, options)\n\nExpress middleware to validate a Joi schema using the `express-validation` module. This will throw an error as an instance of ExpressValidationError if the Joi validation fails.\n\n```javascript\nconst schema =   {\n  body: Joi.object({\n    name: Joi.string().required(),\n  })\n};\n\napp.post('/my-endpoint', treehouse.validateSchema(schema), ...);\n```\n\n- [All available express-validation options](https://github.com/AndrewKeig/express-validation)\n\n## Tests\n\n- You can run `npm run test` to run all tests\n- You can run `npm run test:coverage` to run all tests with coverage report\n\n## Bugs\n\nWhen you find issues, please report them:\n\n- web: [https://github.com/icapps/tree-house/issues](https://github.com/icapps/tree-house/issues)\n\nBe sure to include all of the output from the npm command that didn't work as expected. The npm-debug.log file is also helpful to provide.\n\n## Authors\n\nSee the list of [contributors](https://github.com/icapps/tree-house/contributors) who participated in this project.\n\n## License\n\nThis project is licensed under the ISC License - see the [LICENSE.md](LICENSE.md) file for details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficapps%2Ftree-house","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ficapps%2Ftree-house","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficapps%2Ftree-house/lists"}