{"_id":"@cmts-dev/carmentis-sdk-json-rpc","_rev":"2-95f729f2bbc1011dbfd27e97fa246862","name":"@cmts-dev/carmentis-sdk-json-rpc","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.2":{"name":"@cmts-dev/carmentis-sdk-json-rpc","version":"1.0.2","_id":"@cmts-dev/carmentis-sdk-json-rpc@1.0.2","maintainers":[{"name":"gamarcad","email":"gael.marcadet@carmentis.io"}],"dist":{"shasum":"78315463d9060eda8d7af50f8da681ec31aa15ae","tarball":"https://registry.npmjs.org/@cmts-dev/carmentis-sdk-json-rpc/-/carmentis-sdk-json-rpc-1.0.2.tgz","fileCount":9,"integrity":"sha512-yukZjg25TFs43WwaFlJSiknVeTUT5Bvi3fSk+NWE3VKTnqgaasuFZVSzDEQZmytn/t0k2NJoo5t7A9TheMRjwg==","signatures":[{"sig":"MEUCIA4yzbrK7nrqbpbLcymsks4eSoQ+8YEUgdj73czaQXWcAiEAvTbNNmvWZNt0oeS2gfwH3cYnMApYKrX02uCGVmVkRUY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29174},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"693b12f90dbbee276782f2bcacaa156c6f5ea735","licence":"Apache 2.0","private":false,"scripts":{"test":"jest","build":"vite build"},"_npmUser":{"name":"gamarcad","email":"gael.marcadet@carmentis.io"},"_npmVersion":"10.9.4","description":"SDK for parsing and building JSON-RPC 2.0 messages","directories":{},"_nodeVersion":"22.22.1","dependencies":{"valibot":"^1.3.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.3.0","vite":"^8.0.3","ts-jest":"^29.4.6","typescript":"^5.5.3","@types/jest":"^30.0.0","vite-plugin-dts":"^4.5.4","semantic-release":"^24.2.0","@semantic-release/git":"^10.0.1","@semantic-release/changelog":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/carmentis-sdk-json-rpc_1.0.2_1774528911267_0.28623572052631396","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-03-26T12:41:51.188Z","modified":"2026-05-21T09:16:58.936Z","1.0.2":"2026-03-26T12:41:51.412Z"},"description":"SDK for parsing and building JSON-RPC 2.0 messages","maintainers":[{"email":"arnauld.chevallier@carmentis.io","name":"a.rnauld"},{"email":"gael.marcadet@carmentis.io","name":"gamarcad"}],"readme":"# @cmts-dev/carmentis-sdk-json-rpc\n\nTypeScript SDK for parsing and building [JSON-RPC 2.0](https://www.jsonrpc.org/specification) messages, with runtime validation powered by [valibot](https://valibot.dev).\n\n## Installation\n\n```bash\nnpm install @cmts-dev/carmentis-sdk-json-rpc valibot\n```\n\n## Quick start\n\n```ts\nimport { JsonRpc } from \"@cmts-dev/carmentis-sdk-json-rpc\";\n\n// Parse an incoming request (string or object)\nconst result = JsonRpc.parseRequest(rawInput);\n\nif (!result.ok) {\n  // result.error is a ready-to-send JsonRpcErrorResponse\n  send(result.error);\n} else if (JsonRpc.isRequest(result.value)) {\n  // Regular request — you must reply\n  const { method, params, id } = result.value;\n  send(JsonRpc.success(id, { answer: 42 }));\n} else {\n  // Notification — no reply needed\n  const { method, params } = result.value;\n}\n```\n\n---\n\n## API\n\n### `JsonRpc` — static class\n\n#### Parsing\n\n| Method | Description |\n|---|---|\n| `JsonRpc.parse(input)` | Auto-detects single request or batch |\n| `JsonRpc.parseRequest(input)` | Parses a single request or notification |\n| `JsonRpc.parseBatch(input)` | Parses a batch array |\n\nAll parse methods accept either a `string` (raw JSON) or a pre-parsed value.\nThey return a `ParseResult<T>`: `{ ok: true, value }` or `{ ok: false, error }`.\n\n`parseBatch` returns `ParseResult<BatchParseResult>` where `value.valid` holds the valid items and `value.errors` holds per-item error responses.\n\n#### Building responses\n\n```ts\nJsonRpc.success(id, result)        // { jsonrpc: \"2.0\", result, id }\nJsonRpc.error(id, code, message)   // generic error response\nJsonRpc.parseError()               // code -32700\nJsonRpc.invalidRequest(id?)        // code -32600\nJsonRpc.methodNotFound(id)         // code -32601\nJsonRpc.invalidParams(id)          // code -32602\nJsonRpc.internalError(id)          // code -32603\n```\n\n#### Error codes\n\n```ts\nJsonRpc.ErrorCode.ParseError      // -32700\nJsonRpc.ErrorCode.InvalidRequest  // -32600\nJsonRpc.ErrorCode.MethodNotFound  // -32601\nJsonRpc.ErrorCode.InvalidParams   // -32602\nJsonRpc.ErrorCode.InternalError   // -32603\n```\n\n#### Type guards\n\n```ts\nJsonRpc.isRequest(req)          // req is JsonRpcRequest\nJsonRpc.isNotification(req)     // req is JsonRpcNotification\nJsonRpc.isSuccessResponse(res)  // res is JsonRpcSuccessResponse\nJsonRpc.isErrorResponse(res)    // res is JsonRpcErrorResponse\nJsonRpc.isBatchResult(value)    // value is BatchParseResult\n```\n\n---\n\n## Examples\n\n### Single request / response\n\n```ts\n// --> {\"jsonrpc\":\"2.0\",\"method\":\"subtract\",\"params\":[42,23],\"id\":1}\nconst result = JsonRpc.parseRequest(input);\n// <-- {\"jsonrpc\":\"2.0\",\"result\":19,\"id\":1}\nsend(JsonRpc.success(1, 19));\n```\n\n### Notification (no reply)\n\n```ts\n// --> {\"jsonrpc\":\"2.0\",\"method\":\"update\",\"params\":[1,2,3,4,5]}\nconst result = JsonRpc.parseRequest(input);\nif (result.ok && JsonRpc.isNotification(result.value)) {\n  // process silently, do not send a response\n}\n```\n\n### Batch request\n\n```ts\n// --> [{\"jsonrpc\":\"2.0\",\"method\":\"sum\",\"params\":[1,2,4],\"id\":\"1\"}, ...]\nconst result = JsonRpc.parseBatch(input);\nif (!result.ok) {\n  return send(result.error); // invalid JSON or empty array\n}\n\nconst responses: JsonRpcResponse[] = [];\n\nfor (const req of result.value.valid) {\n  if (JsonRpc.isNotification(req)) continue; // no reply for notifications\n  const dispatch = registry.dispatch(req);\n  responses.push(\n    dispatch.ok\n      ? JsonRpc.success(req.id, await handle(dispatch))\n      : dispatch.error\n  );\n}\n\n// Include per-item parse errors in the batch response\nresponses.push(...result.value.errors);\n\nif (responses.length > 0) send(responses);\n```\n\n### Error handling\n\n```ts\nconst result = JsonRpc.parseRequest(input);\nif (!result.ok) {\n  // Already a valid JsonRpcErrorResponse, send it directly\n  return send(result.error);\n}\n\ntry {\n  const value = await processRequest(result.value);\n  send(JsonRpc.success(result.value.id, value));\n} catch (err) {\n  send(JsonRpc.internalError(result.value.id, { message: String(err) }));\n}\n```\n\n---\n\n## Types\n\n```ts\ntype JsonRpcId = string | number | null;\ntype JsonRpcParams = unknown[] | Record<string, unknown>;\n\ninterface JsonRpcRequest<P = JsonRpcParams> { jsonrpc: \"2.0\"; method: string; params?: P; id: JsonRpcId }\ninterface JsonRpcNotification<P = JsonRpcParams> { jsonrpc: \"2.0\"; method: string; params?: P }\ninterface JsonRpcSuccessResponse<T = unknown> { jsonrpc: \"2.0\"; result: T; id: JsonRpcId }\ninterface JsonRpcErrorResponse { jsonrpc: \"2.0\"; error: JsonRpcError; id: JsonRpcId }\ninterface JsonRpcError { code: number; message: string; data?: unknown }\n\ninterface BatchParseResult {\n  valid: Array<JsonRpcRequest | JsonRpcNotification>;\n  errors: Array<JsonRpcErrorResponse>;\n}\n\ntype ParseResult<T> = { ok: true; value: T } | { ok: false; error: JsonRpcErrorResponse };\n```\n","readmeFilename":"README.md"}