{"_id":"@amit-kandar/response-handler","_rev":"2-8983bb73e5f63ac4c636733744fc34d6","name":"@amit-kandar/response-handler","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@amit-kandar/response-handler","version":"1.0.0","keywords":["response","error","rest","socket.io"],"author":{"name":"Amit Kandar"},"license":"ISC","_id":"@amit-kandar/response-handler@1.0.0","maintainers":[{"name":"amit-kandar","email":"kandaramit2001@gmail.com"}],"homepage":"https://github.com/amit-kandar/response-handler#readme","bugs":{"url":"https://github.com/amit-kandar/response-handler/issues"},"dist":{"shasum":"de564fce7fdb44dd1d797b8d248b54790f311a8f","tarball":"https://registry.npmjs.org/@amit-kandar/response-handler/-/response-handler-1.0.0.tgz","fileCount":37,"integrity":"sha512-0KfkgQ8bY7t64ibgu+Fn/8eIf3+uPCU8ouep+UBdWKny/XRK9MN/LTaQJLLo6SSKhAHixgVmQO/TR19gkWizag==","signatures":[{"sig":"MEQCIGQPv7WFo1+KxsvynGpVWoX6gPd+X2sqzUXy6JC05bYqAiBx2762kFcyjFO2tL5wMTy3Yw4aApX+AysmHIfHczcDiw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":85718},"main":"dist/index.js","types":"dist/index.d.ts","config":{"commitizen":{"path":"cz-conventional-changelog"}},"gitHead":"700d6db47a22c27cb177ab12d959162aaa9b01eb","scripts":{"dev":"nodemon --exec ts-node ./src/index.ts","lint":"eslint . --ext .ts","test":"jest","build":"tsc","start":"node ./dist/index.js","format":"prettier --write .","prepare":"husky && git config core.hooksPath .husky || true","docs:dev":"vitepress dev","test:e2e":"jest --selectProjects e2e","test:unit":"jest --selectProjects unit","docs:build":"vitepress build","test:watch":"jest --watch","docs:preview":"vitepress preview","test:coverage":"jest --coverage","prepublishOnly":"npm run build && npm test -- --runInBand","test:integration":"jest --selectProjects integration"},"_npmUser":{"name":"amit-kandar","email":"kandaramit2001@gmail.com"},"repository":{"url":"git+https://github.com/amit-kandar/response-handler.git","type":"git"},"_npmVersion":"10.9.2","description":"Unified response and error handler for REST APIs and Socket.IO","directories":{},"lint-staged":{"*.{js,json,md}":["prettier --write"],"src/**/*.{ts,tsx}":["eslint --fix","prettier --write"]},"_nodeVersion":"22.14.0","dependencies":{"express":"^5.1.0","socket.io":"^4.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","tsup":"^8.5.0","husky":"^9.1.7","eslint":"^8.57.1","ts-jest":"^29.3.4","ts-node":"^10.9.2","prettier":"^3.5.3","supertest":"^7.0.0","vitepress":"^1.6.3","commitizen":"^4.3.1","typescript":"^5.8.3","@types/jest":"^29.5.14","@types/node":"^22.15.30","lint-staged":"^16.1.0","@types/express":"^5.0.3","@commitlint/cli":"^19.8.1","@types/socket.io":"^3.0.2","@types/supertest":"^6.0.2","socket.io-client":"^4.8.1","eslint-plugin-import":"^2.31.0","eslint-config-prettier":"^10.1.5","eslint-plugin-prettier":"^5.4.1","@types/socket.io-client":"^3.0.0","@typescript-eslint/parser":"^8.33.1","cz-conventional-changelog":"^3.3.0","eslint-config-airbnb-base":"^15.0.0","@commitlint/config-conventional":"^19.8.1","@typescript-eslint/eslint-plugin":"^8.33.1"},"_npmOperationalInternal":{"tmp":"tmp/response-handler_1.0.0_1771664911164_0.3691479643510778","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@amit-kandar/response-handler","version":"1.0.1","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"start":"node ./dist/index.js","dev":"nodemon --exec ts-node ./src/index.ts","test":"jest","test:unit":"jest --selectProjects unit","test:integration":"jest --selectProjects integration","test:e2e":"jest --selectProjects e2e","test:watch":"jest --watch","test:coverage":"jest --coverage","build":"tsc","docs:dev":"vitepress dev","docs:build":"vitepress build","docs:preview":"vitepress preview","lint":"eslint . --ext .ts","format":"prettier --write .","prepare":"husky && git config core.hooksPath .husky || true","prepublishOnly":"npm run build && npm test -- --runInBand"},"lint-staged":{"src/**/*.{ts,tsx}":["eslint --fix","prettier --write"],"*.{js,json,md}":["prettier --write"]},"config":{"commitizen":{"path":"cz-conventional-changelog"}},"keywords":["response","error","rest","socket.io"],"author":{"name":"Amit Kandar"},"homepage":"https://response-handler.vercel.app/","repository":{"type":"git","url":"git+https://github.com/amit-kandar/response-handler.git"},"bugs":{"url":"https://github.com/amit-kandar/response-handler/issues"},"publishConfig":{"access":"public"},"license":"ISC","dependencies":{"express":"^5.1.0","socket.io":"^4.8.1"},"devDependencies":{"@commitlint/cli":"^19.8.1","@commitlint/config-conventional":"^19.8.1","@types/express":"^5.0.3","@types/jest":"^29.5.14","@types/node":"^22.15.30","@types/socket.io":"^3.0.2","@types/socket.io-client":"^3.0.0","@types/supertest":"^6.0.2","@typescript-eslint/eslint-plugin":"^8.33.1","@typescript-eslint/parser":"^8.33.1","commitizen":"^4.3.1","cz-conventional-changelog":"^3.3.0","eslint":"^8.57.1","eslint-config-airbnb-base":"^15.0.0","eslint-config-prettier":"^10.1.5","eslint-plugin-import":"^2.31.0","eslint-plugin-prettier":"^5.4.1","husky":"^9.1.7","jest":"^29.7.0","lint-staged":"^16.1.0","prettier":"^3.5.3","socket.io-client":"^4.8.1","supertest":"^7.0.0","ts-jest":"^29.3.4","ts-node":"^10.9.2","tsup":"^8.5.0","typescript":"^5.8.3","vitepress":"^1.6.3"},"description":"Unified response and error handler for REST APIs and Socket.IO","_id":"@amit-kandar/response-handler@1.0.1","gitHead":"522242535f4e0ffcc78dc1daf5a9e01d4787eb47","_nodeVersion":"22.14.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-4pzRkB7bF5BXAH2HUAfN7lscptac0ezUuz9xppnW56i5ryhwvrc2a8BVSN/qhNAvdpQSGIoQ4/O0MRVhFHQ+4w==","shasum":"c0fef2ec32195d4741d16e14f68fd726a4995476","tarball":"https://registry.npmjs.org/@amit-kandar/response-handler/-/response-handler-1.0.1.tgz","fileCount":37,"unpackedSize":85857,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCwJeVtIsEGm7ACVYWot3b4xVPCif6cPiLSp50G3MBO6QIgR8j+fGHS6uX3UCXniZ8PLrHycZsivvVEm/bQz4ZlKhs="}]},"_npmUser":{"name":"amit-kandar","email":"kandaramit2001@gmail.com"},"directories":{},"maintainers":[{"name":"amit-kandar","email":"kandaramit2001@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/response-handler_1.0.1_1771665612468_0.8053479563000185"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-21T09:08:31.014Z","modified":"2026-02-21T09:20:13.082Z","1.0.0":"2026-02-21T09:08:31.311Z","1.0.1":"2026-02-21T09:20:12.613Z"},"bugs":{"url":"https://github.com/amit-kandar/response-handler/issues"},"author":{"name":"Amit Kandar"},"license":"ISC","homepage":"https://response-handler.vercel.app/","keywords":["response","error","rest","socket.io"],"repository":{"type":"git","url":"git+https://github.com/amit-kandar/response-handler.git"},"description":"Unified response and error handler for REST APIs and Socket.IO","maintainers":[{"name":"amit-kandar","email":"kandaramit2001@gmail.com"}],"readme":"# Response Handler\n\nUnified response and error handling for Express and Socket.IO.\n\nThis package provides one entry point for both modern middleware-driven usage and legacy adapter compatibility.\n\n## Installation\n\n```bash\nnpm install @amit-kandar/response-handler\n```\n\n## Quick Start\n\n### Express (recommended)\n\n```ts\nimport express from 'express';\nimport { quickSetup } from '@amit-kandar/response-handler';\n\nconst app = express();\napp.use(express.json());\n\nconst { middleware, errorHandler } = quickSetup({\n  mode: 'development',\n  logging: { enabled: true, logErrors: true },\n  security: {\n    sanitizeErrors: true,\n    rateLimiting: { windowMs: 60_000, maxRequests: 100 },\n  },\n  responses: {\n    includeRequestId: true,\n    includeTimestamp: true,\n    includeExecutionTime: true,\n  },\n  performance: {\n    enableCaching: true,\n    cacheTTL: 120,\n  },\n});\n\napp.use(middleware);\n\napp.get('/users', async (_req, res) => {\n  const users = await Promise.resolve([{ id: 1, name: 'Amit' }]);\n  return res.ok(users, 'Users retrieved');\n});\n\napp.get('/users/:id', async (req, res) => {\n  if (!req.params.id) return res.badRequest({ field: 'id' }, 'Missing user id');\n  return res.notFound({ id: req.params.id }, 'User not found');\n});\n\napp.use(errorHandler);\napp.listen(3000);\n```\n\n### Socket.IO\n\n```ts\nimport { createSocketHandler } from '@amit-kandar/response-handler';\n\nconst socketHandler = createSocketHandler({ mode: 'development' });\n\nio.on('connection', (socket) => {\n  socket.on('user:get', async (payload) => {\n    const response = socketHandler.enhance(socket, 'user:result');\n\n    if (!payload?.id) return response.badRequest({ field: 'id' }, 'Missing id');\n\n    response.ok({ id: payload.id, name: 'Amit' }, 'User loaded');\n  });\n});\n```\n\n## Express API\n\n### Success methods\n\n- `res.ok(data?, message?)` -> `200`\n- `res.created(data?, message?)` -> `201`\n- `res.accepted(data?, message?)` -> `202`\n- `res.noContent(message?)` -> `204` (empty body)\n\n### Error methods\n\n- `res.badRequest(error?, message?)` -> `400`\n- `res.unauthorized(error?, message?)` -> `401`\n- `res.forbidden(error?, message?)` -> `403`\n- `res.notFound(error?, message?)` -> `404`\n- `res.conflict(error?, message?)` -> `409`\n- `res.unprocessableEntity(error?, message?)` -> `422`\n- `res.tooManyRequests(error?, message?)` -> `429`\n- `res.internalServerError(error?, message?)` -> `500`\n- `res.error(error, statusCode?)` -> auto status from error or fallback `500`\n\n### Generic methods\n\n- `res.respond(statusCode, data?, message?)`\n- `res.paginate(data, pagination, message?)`\n- `res.downloadFile(path, filename?)`\n- `res.streamResponse(stream, contentType?)`\n\n## Socket API\n\nCreate a response object with:\n\n- `createSocketHandler(config).enhance(socket, event)`\n\nMethods:\n\n- `ok`, `created`\n- `error`, `badRequest`, `unauthorized`, `forbidden`, `notFound`\n- `emit(event, data?, statusCode?)`\n- `toRoom(room)`\n- `toSocket(socketId)`\n\n## Configuration\n\n```ts\nconst config = {\n  mode: 'production', // or development\n\n  logging: {\n    enabled: true,\n    level: 'info', // error | warn | info | debug\n    logErrors: true,\n    logRequests: false,\n    logResponses: false,\n    includeStack: false,\n    includeRequest: false,\n  },\n\n  responses: {\n    includeTimestamp: true,\n    includeRequestId: true,\n    includeExecutionTime: true,\n    customFields: { service: 'api' },\n    compression: false,\n    compressionThreshold: 1024,\n  },\n\n  security: {\n    sanitizeErrors: true,\n    hideInternalErrors: true,\n    allowedErrorFields: ['message', 'type', 'code'],\n    corsHeaders: false,\n    rateLimiting: {\n      windowMs: 60_000,\n      maxRequests: 100,\n      statusCode: 429,\n      message: 'Too many requests',\n    },\n  },\n\n  performance: {\n    enableCaching: false,\n    cacheHeaders: false,\n    cacheControl: '',\n    cacheTTL: 0,\n    etag: true,\n    compression: false,\n    compressionThreshold: 1024,\n  },\n};\n```\n\n## Legacy Adapter Compatibility\n\nLegacy helpers are still exported from the same package entry:\n\n- REST: `sendSuccess`, `sendError`, `errorHandler`\n- Socket: `emitSuccess`, `emitError`, `socketWrapper`\n\nThey are maintained as thin compatibility adapters over the unified response contract.\n\n## Formatter Customization\n\nYou can override the response payload template with:\n\n- `setResponseFormatter(fn)`\n\nBackward-compatible aliases are also exported:\n\n- `configureResponseFormat`\n- `formatApiResponse`\n- `getFormattedResponse`\n\n## Exports Overview\n\nMain exports from `@amit-kandar/response-handler`:\n\n- `quickSetup`, `quickSocketSetup`\n- `ResponseHandler`, `createResponseHandler`, `defaultResponseHandler`, `responseHandler`\n- `SocketResponseHandler`, `createSocketHandler`\n- `ResponseBuilder`, `Logger`\n- Error classes: `AppError`, `ValidationError`, `NotFoundError`, `UnauthorizedError`\n- Legacy adapters and formatter helpers\n\n## Behavior Notes\n\n- Request IDs are generated with `crypto.randomUUID()` when missing.\n- `security.sanitizeErrors` controls whether errors are filtered to allowed fields or preserved in full.\n- Production mode can hide internal error details.\n- `204 No Content` responses send an empty body.\n- `respond(statusCode, ...)` treats `>= 400` as error response semantics.\n- Compression uses async gzip when enabled and client accepts `gzip`.\n- Rate limiting returns `X-RateLimit-*` headers on allowed/blocked requests and `Retry-After` on `429`.\n\n## Development\n\n```bash\nnpm run lint\nnpm run build\nnpm test\nnpm run test:unit\nnpm run test:integration\nnpm run test:e2e\n```\n\n## Documentation\n\n- Docs source: `docs/`\n- VitePress config: `.vitepress/config.js`\n- Main sections:\n  - `docs/guide/`\n  - `docs/api/`\n  - `docs/examples/`\n  - `docs/deployment/`\n\n## License\n\nISC © Amit Kandar\n","readmeFilename":"README.md"}