{"_id":"@ably-labs/local-proxy","name":"@ably-labs/local-proxy","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@ably-labs/local-proxy","version":"0.0.1","description":"Local proxy for SDK testing","scripts":{"build":"tsc","prepare":"npm run build","test":"vitest run"},"author":{"name":"Ably Ecosystems Team"},"license":"MIT","dependencies":{"ably":"^2.3.1","http-proxy":"^1.18.1","ws":"^8.16.0"},"devDependencies":{"@types/express":"^4.17.21","@types/http-proxy":"^1.17.16","@types/jsonwebtoken":"^9.0.7","@types/ws":"^8.5.12","esbuild-runner":"^2.2.2","prettier":"^3.2.5","typescript":"^5.5.4","vitest":"^1.6.0"},"_id":"@ably-labs/local-proxy@0.0.1","gitHead":"dd96ae970952bfc4ab0e80e444bb0739aa57bc2e","_nodeVersion":"20.10.0","_npmVersion":"10.2.3","dist":{"integrity":"sha512-9P9szuk3RA23uiqCRouTEBOmfJ9YoQXGI4KgKzsfr00ChaG8WrpyI8pL7hB6HsXmLX/I5Q9ot725w7d04mefSg==","shasum":"d18d63571fc044d35f42a69766839f93fee2bfd8","tarball":"https://registry.npmjs.org/@ably-labs/local-proxy/-/local-proxy-0.0.1.tgz","fileCount":24,"unpackedSize":64860,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCdhK0NqQS8W7WDspKiH+EO88TKYmKVM4FbWd864iS9NQIgV+891jvO9yMxW0GDkBk/zMRLf6IQ4rb24DUv2GVXWyg="}]},"_npmUser":{"name":"ttypic","email":"khokhlov.e.n@gmail.com"},"directories":{},"maintainers":[{"name":"andrii.bulat.ably","email":"andrii.bulat@ably.com"},{"name":"mschristensen","email":"mike@christensen.codes"},{"name":"ttypic","email":"khokhlov.e.n@gmail.com"},{"name":"ably-labs-user","email":"devrel@ably.com"},{"name":"lmars","email":"lewis@lmars.net"},{"name":"owenpearson","email":"owen.pearson@ably.com"},{"name":"ably-realtime","email":"account.owners@ably.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/local-proxy_0.0.1_1758619662523_0.25977442155881736"},"_hasShrinkwrap":false}},"time":{"created":"2025-09-23T09:27:42.445Z","0.0.1":"2025-09-23T09:27:42.737Z","modified":"2025-09-23T09:27:43.100Z"},"maintainers":[{"name":"andrii.bulat.ably","email":"andrii.bulat@ably.com"},{"name":"mschristensen","email":"mike@christensen.codes"},{"name":"ttypic","email":"khokhlov.e.n@gmail.com"},{"name":"ably-labs-user","email":"devrel@ably.com"},{"name":"lmars","email":"lewis@lmars.net"},{"name":"owenpearson","email":"owen.pearson@ably.com"},{"name":"ably-realtime","email":"account.owners@ably.com"}],"description":"Local proxy for SDK testing","author":{"name":"Ably Ecosystems Team"},"license":"MIT","readme":"# Local HTTP & WebSocket Proxy for SDK Testing\n\nDuring SDK testing, it’s often useful to simulate real-world conditions or inspect communication between a client and a backend service. This lightweight local proxy helps developers spy on and inject both HTTP and WebSocket traffic for more effective debugging, experimentation, and test automation.\n\n## ✨ Core Features\n\n### 🔍 HTTP Inspection\n\n- Spy on Outgoing HTTP Requests\n- Modify Incoming HTTP Responses\n\n### 🔍 WebSocket Inspection\n\n- Spy on Outgoing WebSocket Messages\n- Modify Incoming WebSocket Messages\n- Inject WebSocket Messages\n\n### 📦 Use Cases\n\n- Validate SDK behavior against specific message sequences.\n- Simulate dropped or malformed responses.\n- Replay server messages for automated or regression testing.\n- Monitor raw protocol-level activity to catch subtle bugs or race conditions.\n\n### 🚀 Getting Started\n\nInstall npm dependency:\n\n```bash\nnpm install --save-dev @ably-labs/local-proxy\n```\n\n### 🧪 Basic Usage\n\n```ts\nimport { createInterceptingProxy } from '@ably-labs/local-proxy';\n\n// 1. Create and start the proxy\nconst proxy = createInterceptingProxy({\n  // options here realtimeHost, restHost\n});\nawait proxy.start();\n\n// 2. Configure your SDK to use proxy.options\nconst client = new Ably.Realtime({\n  ...proxy.options\n  // aditonal option\n});\n\n// 3. Observe an outgoing HTTP request\nconst request = await proxy.observeNextRequest(req =>\n  req.url.includes('/channels')\n);\n\n// 4. Observe an incoming protocol message\nproxy.observeNextIncomingProtocolMessage(msg =>\n  msg.action === 15 // Presence message\n)\n\n// 5. Inject a fake message into the client\nproxy.injectProtocolMessage(client.connection.id, {\n    action: 9, // Example: SYNC\n    channel: 'room:test',\n    connectionId: client.connection.id,\n    msgSerial: 0,\n    connectionSerial: -1,\n    data: { custom: 'data' },\n});\n```\n\n### 🧩 Replace a Server Message\n\nYou can also simulate faulty server responses:\n\n```ts\nproxy.replaceNextIncomingProtocolMessage(\n  {\n    action: 9, // Fake SYNC\n    channel: 'room:test',\n    data: [],\n  },\n  msg => msg.action === 9 // Replace only SYNC messages\n);\n```\n\n\n### 🔌 Drop or Pause a Connection\n\n```ts\n// Drop connection by ID (force disconnect)\nproxy.dropConnection(client.connection.id);\n\n// Pause and resume connection manually\nconst resume = proxy.pauseConnection();\n// simulate a pause...\nsetTimeout(() => resume(), 5000);\n```\n\n\n### 🔧 Register Middleware\n\nFor more advanced use cases, register middlewares to continuously inspect or modify traffic:\n\n```ts\nconst unregister = proxy.registerRestMiddleware(req => {\n  if (req.url.includes('/channels')) {\n    console.log('Intercepted REST request:', req);\n    // You can modify headers, body, or response here\n  }\n});\n// Later...\nunregister();\n```\n","readmeFilename":"README.md","_rev":"1-7c8c49d9fdaf33a19b7573853748569b"}