{"_id":"@avelor/mesh","_rev":"6-25b7762974bd395262e2981062eac11d","name":"@avelor/mesh","dist-tags":{"latest":"0.4.1"},"versions":{"0.1.0":{"name":"@avelor/mesh","version":"0.1.0","keywords":["proxy","dev","local","localhost","https","hosts","dns","chaos","fault-injection","developer-tools"],"author":{"name":"Avelor","email":"cruz@avelor.es"},"license":"MIT","_id":"@avelor/mesh@0.1.0","maintainers":[{"name":"christianecg","email":"contacto@christianecg.com"}],"homepage":"https://github.com/avelor-es/mesh#readme","bugs":{"url":"https://github.com/avelor-es/mesh/issues"},"bin":{"mesh":"bin/mesh.js"},"dist":{"shasum":"dba4f74f925918418f45e0076b30422e13f3109a","tarball":"https://registry.npmjs.org/@avelor/mesh/-/mesh-0.1.0.tgz","fileCount":10,"integrity":"sha512-okYb7U1Xwmii78dbn77wLh7q07qIX/v7Uib8KKdi0twGQIhssYAmFoQ2GT5ebr+QNEe5CKDjCm8UyKUhWH/qxQ==","signatures":[{"sig":"MEYCIQCXb+1naqO3H3g94U8Wr9SaXB6byWBUuBEkrkMqNkjflQIhAMy3SXrqPY8WIu4B2ScTshSu/AeX2PZAvjMFszGZYv+k","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":20371},"type":"module","engines":{"node":">=18"},"_npmUser":{"name":"christianecg","email":"contacto@christianecg.com"},"repository":{"url":"git+https://github.com/avelor-es/mesh.git","type":"git"},"_npmVersion":"11.6.2","description":"Local dev proxy. Named services, failure rules, no ports.","directories":{},"_nodeVersion":"24.13.0","dependencies":{"js-yaml":"^4.1.0","http-proxy":"^1.18.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/mesh_0.1.0_1780350167295_0.5940573804206346","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@avelor/mesh","version":"0.2.0","keywords":["proxy","dev","local","localhost","https","hosts","dns","chaos","fault-injection","developer-tools"],"author":{"name":"Avelor","email":"cruz@avelor.es"},"license":"MIT","_id":"@avelor/mesh@0.2.0","maintainers":[{"name":"christianecg","email":"contacto@christianecg.com"}],"homepage":"https://github.com/avelor-es/mesh#readme","bugs":{"url":"https://github.com/avelor-es/mesh/issues"},"bin":{"mesh":"bin/mesh.js"},"dist":{"shasum":"b29f36f5eb56897198412d6f779dd3b9491c4b8e","tarball":"https://registry.npmjs.org/@avelor/mesh/-/mesh-0.2.0.tgz","fileCount":11,"integrity":"sha512-2xYdCt5xuDh4va1vKcm6thmcrmPTIfGJiocAeqw7RECIz8Ai7Y7FB7oCmxA4/NpNVN9DwtE6+YRA/eI1O3PXtQ==","signatures":[{"sig":"MEQCIADrlZ70hdNBsMOs4y2yXfUTUHvdprIvj8a7Q5OMJjSNAiA0ZW/wro1jTZfzDtTXbIwV2rnEWTCV53nj1ANu1fHKyg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27902},"type":"module","engines":{"node":">=18"},"gitHead":"92229dcca64a34a04b90a906cdf655fe04c85746","scripts":{"test":"node --test test/*.test.js"},"_npmUser":{"name":"christianecg","email":"contacto@christianecg.com"},"repository":{"url":"git+https://github.com/avelor-es/mesh.git","type":"git"},"_npmVersion":"11.6.2","description":"Local dev proxy. Named services, failure rules, no ports.","directories":{},"_nodeVersion":"24.13.0","dependencies":{"js-yaml":"^4.1.0","http-proxy":"^1.18.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/mesh_0.2.0_1780374239990_0.9543546376411367","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@avelor/mesh","version":"0.2.1","keywords":["proxy","dev","local","localhost","https","hosts","dns","chaos","fault-injection","developer-tools"],"author":{"name":"Avelor","email":"cruz@avelor.es"},"license":"MIT","_id":"@avelor/mesh@0.2.1","maintainers":[{"name":"christianecg","email":"contacto@christianecg.com"}],"homepage":"https://github.com/avelor-es/mesh#readme","bugs":{"url":"https://github.com/avelor-es/mesh/issues"},"bin":{"mesh":"bin/mesh.js"},"dist":{"shasum":"b956f5988a388574db4d2cbc96574152824f060a","tarball":"https://registry.npmjs.org/@avelor/mesh/-/mesh-0.2.1.tgz","fileCount":11,"integrity":"sha512-5YaCkzGASdm0/Tmz4wgAc5tbhfMzcfe/3wCK/cSJVR+eG+D1Ttyb0S46TQa0te8DTFF0vbdSZpOnpJw/jv4tfw==","signatures":[{"sig":"MEUCIGSIn9aA4z1DU1a+HP1yLAMbdpZLGdVRXuVNUXFID/SUAiEAjhHFP24Ib1ffac4jWlOHDEpJUwVbkpudVXHuyKLwfGM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29855},"type":"module","engines":{"node":">=18"},"gitHead":"c886b095824ed35395b4d3b1c728bfff20fdcd74","scripts":{"test":"node --test test/*.test.js"},"_npmUser":{"name":"christianecg","email":"contacto@christianecg.com"},"repository":{"url":"git+https://github.com/avelor-es/mesh.git","type":"git"},"_npmVersion":"11.6.2","description":"Local dev proxy. Named services, failure rules, no ports.","directories":{},"_nodeVersion":"24.13.0","dependencies":{"js-yaml":"^4.1.0","http-proxy":"^1.18.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/mesh_0.2.1_1780462835881_0.49098255634103527","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@avelor/mesh","version":"0.3.0","keywords":["proxy","dev","local","localhost","https","hosts","dns","chaos","fault-injection","developer-tools"],"author":{"name":"Avelor","email":"cruz@avelor.es"},"license":"MIT","_id":"@avelor/mesh@0.3.0","maintainers":[{"name":"christianecg","email":"contacto@christianecg.com"}],"homepage":"https://github.com/avelor-es/mesh#readme","bugs":{"url":"https://github.com/avelor-es/mesh/issues"},"bin":{"mesh":"bin/mesh.js"},"dist":{"shasum":"900d0fb5c3b60667920bdaaac7270ceeecad4de3","tarball":"https://registry.npmjs.org/@avelor/mesh/-/mesh-0.3.0.tgz","fileCount":11,"integrity":"sha512-GATah4AOiqH7fGdh1Ofcuq3Wxjz/xnJjS0Q+VUlHMtKpABTzlGlvjwJmXyB3Ko0LkgySJxDXEufk9/4cv2Cf5g==","signatures":[{"sig":"MEYCIQCITAMHkpKmHM4yMPG1nfWU016/La3HnubmSyZAYZQ5RgIhANKDBUT8HJbSpqRc+2qqnyJEnyXLGp8e69F2OEbEaK60","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30237},"type":"module","engines":{"node":">=18"},"gitHead":"0e3dec035302130c462eefeb46323090567ee600","scripts":{"test":"node --test test/*.test.js"},"_npmUser":{"name":"christianecg","email":"contacto@christianecg.com"},"repository":{"url":"git+https://github.com/avelor-es/mesh.git","type":"git"},"_npmVersion":"11.6.2","description":"Local dev proxy. Named services, failure rules, no ports.","directories":{},"_nodeVersion":"24.13.0","dependencies":{"js-yaml":"^4.1.0","http-proxy":"^1.18.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/mesh_0.3.0_1780797955645_0.6688462839762936","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@avelor/mesh","version":"0.4.0","keywords":["proxy","dev","local","localhost","https","hosts","dns","chaos","fault-injection","developer-tools"],"author":{"name":"Avelor","email":"cruz@avelor.es"},"license":"MIT","_id":"@avelor/mesh@0.4.0","maintainers":[{"name":"christianecg","email":"contacto@christianecg.com"}],"homepage":"https://github.com/avelor-es/mesh#readme","bugs":{"url":"https://github.com/avelor-es/mesh/issues"},"bin":{"mesh":"bin/mesh.js"},"dist":{"shasum":"604063aa78107c5510eb6001098effa0d41d68ef","tarball":"https://registry.npmjs.org/@avelor/mesh/-/mesh-0.4.0.tgz","fileCount":12,"integrity":"sha512-ngnv8Jva1xk9tQbyo+09GmQNsABNu5Ue7UTvLibBuP/a3wokvfqELAaB8IbWB23WpzoK6elP0kOcAnyjKzj99g==","signatures":[{"sig":"MEUCIQCRGFWEoIhRkPwSuzYseMYtLywATsDYWMiga1tThh97RgIgbN+NCDPS7SDP2adK1KbMGdkzFn5UK+nq5cGd7/8Tu7I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":35213},"type":"module","engines":{"node":">=18"},"gitHead":"d48208cfd74f7afccfa6240003cf53722b7b3795","scripts":{"test":"node --test test/*.test.js"},"_npmUser":{"name":"christianecg","email":"contacto@christianecg.com"},"repository":{"url":"git+https://github.com/avelor-es/mesh.git","type":"git"},"_npmVersion":"11.6.2","description":"Local dev proxy. Named services, failure rules, no ports.","directories":{},"_nodeVersion":"24.13.0","dependencies":{"js-yaml":"^4.1.0","http-proxy":"^1.18.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/mesh_0.4.0_1780800482696_0.651715788577867","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@avelor/mesh","version":"0.4.1","description":"Local dev proxy. Named services, failure rules, no ports.","keywords":["proxy","dev","local","localhost","https","hosts","dns","chaos","fault-injection","developer-tools"],"license":"MIT","author":{"name":"Avelor","email":"cruz@avelor.es"},"repository":{"type":"git","url":"git+https://github.com/avelor-es/mesh.git"},"publishConfig":{"access":"public"},"type":"module","bin":{"mesh":"bin/mesh.js"},"dependencies":{"http-proxy":"^1.18.1","js-yaml":"^4.1.0"},"scripts":{"test":"node --test test/*.test.js"},"engines":{"node":">=18"},"gitHead":"759c14afd945d1d005079ceaa0c4b79e97021357","_id":"@avelor/mesh@0.4.1","bugs":{"url":"https://github.com/avelor-es/mesh/issues"},"homepage":"https://github.com/avelor-es/mesh#readme","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-y+BFJZWadr2CoYEM86MjHU+Tb60cMYqVmLOebFCEwtd+opjUg3gujqjbtRhCcApTAzQAURp2ixfX3D2z28VD3g==","shasum":"0d785527d00db04d38e2c1c1f8b4f3ec94efda28","tarball":"https://registry.npmjs.org/@avelor/mesh/-/mesh-0.4.1.tgz","fileCount":12,"unpackedSize":36467,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDQH7+R+81G0N52zrwYLtIxH3SEdegFjdphjngC5Fdr1gIhAPEpxYzqd3evnwW0TBm+8mZKX5BEqkC6f1iq4tWvOzge"}]},"_npmUser":{"name":"christianecg","email":"contacto@christianecg.com"},"directories":{},"maintainers":[{"name":"christianecg","email":"contacto@christianecg.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mesh_0.4.1_1780952076652_0.1798546214052723"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-01T21:42:47.176Z","modified":"2026-06-08T20:54:36.931Z","0.1.0":"2026-06-01T21:42:47.456Z","0.2.0":"2026-06-02T04:24:00.134Z","0.2.1":"2026-06-03T05:00:36.029Z","0.3.0":"2026-06-07T02:05:55.805Z","0.4.0":"2026-06-07T02:48:02.835Z","0.4.1":"2026-06-08T20:54:36.806Z"},"bugs":{"url":"https://github.com/avelor-es/mesh/issues"},"author":{"name":"Avelor","email":"cruz@avelor.es"},"license":"MIT","homepage":"https://github.com/avelor-es/mesh#readme","keywords":["proxy","dev","local","localhost","https","hosts","dns","chaos","fault-injection","developer-tools"],"repository":{"type":"git","url":"git+https://github.com/avelor-es/mesh.git"},"description":"Local dev proxy. Named services, failure rules, no ports.","maintainers":[{"name":"christianecg","email":"contacto@christianecg.com"}],"readme":"# mesh\n\nLocal dev proxy. Named services instead of ports. Failure injection without mocks.\n\n![demo](demo.gif)\n\n```\napp.test   → :3000\napi.test   → :4000\nadmin.test → :5000\n```\n\nNo more `:3000`, `:4000`, `:5000` open in different tabs. No more mixing them up.\n\n---\n\n## Install\n\n```bash\nnpm install -g @avelor/mesh\n```\n\nRequires Node.js 18+. For HTTPS, install [mkcert](https://github.com/FiloSottile/mkcert).\n\n---\n\n## Usage\n\n```bash\nmesh init         # create mesh.yml in current directory\nmesh start        # start proxy in background (will prompt for sudo)\nmesh status       # show running services\nmesh stop         # stop the proxy\nmesh route        # start in foreground (useful for debugging)\n```\n\n`mesh start` runs on `:80` and `:443` (if mkcert is available), writes the hostname entries to `/etc/hosts`, and cleans them up automatically on stop.\n\n---\n\n## mesh.yml\n\n```yaml\nservices:\n  app: 3000\n  api: 4000\n  admin: 5000\n```\n\nThat's enough to get started. Services are available at `app.test`, `api.test`, `admin.test`.\n\n### Failure rules\n\nTest how your app handles errors — no mocks, no code changes.\n\n```yaml\nservices:\n  app: 3000\n  api: 4000\n\nrules:\n  api:\n    - path: /payments\n      method: POST\n      status: 503\n      body:\n        error: Payment service unavailable\n        retryAfter: 30\n      rate: 30\n    - path: /auth/login\n      status: 401\n      rate: 20\n    - path: /slow-endpoint\n      delay: 2000\n      rate: 100\n    - path: /flaky\n      status: 500\n      delay: 800\n      rate: 25\n```\n\n| Field    | Description                                                   |\n|----------|---------------------------------------------------------------|\n| `path`   | Request path prefix to match                                  |\n| `method` | HTTP method to match (GET, POST, PUT, PATCH, DELETE…)         |\n| `status` | HTTP status code to return (400, 401, 500, etc.)              |\n| `body`   | Response body — object (sent as JSON) or string (plain text)  |\n| `delay`  | Milliseconds to wait before responding                        |\n| `rate`   | Percentage of matching requests to affect (1–100)             |\n\n`status` and `delay` can be combined: wait N ms, then fail with that status. Without `body`, the default is `{ \"error\": \"<status text>\", \"injected\": true }`.\n\n### Subdomains\n\nMultiple names can point to the same port:\n\n```yaml\nservices:\n  app: 3000\n  tenant1.app: 3000\n  tenant2.app: 3000\n  api: 4000\n```\n\nRules apply per name, so `tenant1.app` and `tenant2.app` can have different failure scenarios.\n\n---\n\n## HTTPS\n\nIf [mkcert](https://github.com/FiloSottile/mkcert) is installed, `mesh route` automatically generates a locally-trusted certificate for all your `.test` domains and serves them over HTTPS. Port `:80` redirects to `:443`.\n\n```bash\n# macOS\nbrew install mkcert\n\n# Linux\napt install mkcert\n```\n\nIf mkcert is not found, mesh falls back to HTTP only.\n\nGenerated certificates are stored in `.mesh/` (added to `.gitignore` by `mesh init`).\n\n---\n\n## Examples\n\nSee [`examples/basic`](examples/basic) and [`examples/multi`](examples/multi) for working setups with a frontend and API server.\n\n```bash\n# terminal 1\ncd examples/basic\nnode api.js\n\n# terminal 2\ncd examples/basic\nnode app.js\n\n# terminal 3 (from examples/basic)\nmesh route\n```\n\nThen open `https://app.test`.\n\n---\n\n## How it works\n\n`mesh route` runs a local HTTP/HTTPS proxy on `127.0.0.1`. Incoming requests are matched by hostname, forwarded to the configured port, and optionally intercepted by failure rules before reaching the target service.\n\n`/etc/hosts` entries are written on start and removed on exit (`SIGINT` / `SIGTERM`).\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}