{"_id":"@atmaca/errors","name":"@atmaca/errors","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@atmaca/errors","version":"0.1.0","description":"Atmaca Errors Package","main":"src/index.js","type":"module","author":{"name":"Alper Kürşat Ünver","email":"kursat@certificatum.org"},"license":"MIT","exports":{".":{"import":"./src/index.js","default":"./src/index.js","types":"./types/index.d.ts"}},"publishConfig":{"access":"public"},"_id":"@atmaca/errors@0.1.0","_nodeVersion":"24.11.1","_npmVersion":"11.3.0","dist":{"integrity":"sha512-Lf9x7oyPyaVbaAtk35+ifj6ym3gqr1oNSTDofm3y9YB/MC3Xg0R5If+T3Tg4xPWs9yeBJQmDDaMm8Q2mA4ft5g==","shasum":"65d4f65ec457ad01f0e0d1bef557d66c27855969","tarball":"https://registry.npmjs.org/@atmaca/errors/-/errors-0.1.0.tgz","fileCount":10,"unpackedSize":32022,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAJh//h0dpdCsumer6d+iUhc6La9/UlXwqpC/3EmAQQ3AiAzNwtM5HWeerxMUxAVT81JyjsSxkj9ESytEUCKH1KwOg=="}]},"_npmUser":{"name":"alperkursat","email":"alperkursatunver@gmail.com"},"directories":{},"maintainers":[{"name":"alperkursat","email":"alperkursatunver@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/errors_0.1.0_1784434297234_0.7456723446312852"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-19T04:11:37.055Z","0.1.0":"2026-07-19T04:11:37.375Z","modified":"2026-07-19T04:11:37.649Z"},"maintainers":[{"name":"alperkursat","email":"alperkursatunver@gmail.com"}],"description":"Atmaca Errors Package","author":{"name":"Alper Kürşat Ünver","email":"kursat@certificatum.org"},"license":"MIT","readme":"# @atmaca/errors\n\n**Dual-Protocol Error Classes for REST and JSON-RPC Services**\n\nThe **@atmaca/errors** package provides a comprehensive set of error classes designed for modern microservices architectures. Each error includes both **REST HTTP status codes** and **JSON-RPC 2.0 error codes**, enabling seamless error translation across protocols.\n\n---\n\n## Features\n\n* **Dual-Protocol Support**: Every error includes both REST and JSON-RPC codes\n* **Rich Context**: Metadata support for detailed error information\n* **Machine-Readable**: Structured reason codes for programmatic handling\n* **Human-Friendly**: Clear, descriptive error messages\n* **Framework Agnostic**: Works with any Node.js framework\n* **Zero Dependencies**: Lightweight and secure\n\n---\n\n## Installation\n\n```bash\nnpm install @atmaca/errors\n```\n\n---\n\n## Quick Start\n\n```js\nimport { NotFoundError, ValidationError } from '@atmaca/errors'\n\n// Throw a not found error\nconst user = await db.users.findById(userId)\nif (!user) {\n  throw new NotFoundError('User', { userId })\n}\n\n// Throw a validation error\nif (age < 18) {\n  throw new ValidationError('age', age, 'must be 18 or older')\n}\n```\n\n---\n\n## Base Error Classes\n\n### RuntimeError\n\nThe base class for all runtime errors in Atmaca applications.\n\n```js\nclass RuntimeError extends Error {\n  name        // Error class name (e.g., \"NotFoundError\")\n  reason      // Machine-readable reason code (e.g., \"user_not_found\")\n  message     // Human-readable error message\n  restCode    // HTTP status code (e.g., 404)\n  jsonRpcCode // JSON-RPC 2.0 error code (e.g., -32002)\n  metadata    // Additional context data\n}\n```\n\n**Example:**\n\n```js\nimport { NotFoundError } from '@atmaca/errors'\n\nconst error = new NotFoundError('User', { userId: 123 })\n\nconsole.log(error.name)        // \"NotFoundError\"\nconsole.log(error.reason)      // \"user_not_found\"\nconsole.log(error.message)     // \"User not found\"\nconsole.log(error.restCode)    // 404\nconsole.log(error.jsonRpcCode) // -32002\nconsole.log(error.metadata)    // { userId: 123 }\n```\n\n### InitializationError\n\nUsed for errors that occur during application initialization.\n\n```js\nclass InitializationError extends Error {\n  name      // \"InitializationError\"\n  reason    // Machine-readable reason code\n  message   // Human-readable error message\n  metadata  // Additional context data\n}\n```\n\n---\n\n## Error Reference\n\n### JSON-RPC 2.0 Specific Errors\n\nThese errors align with the [JSON-RPC 2.0 Specification](https://www.jsonrpc.org/specification):\n\n#### ParseError\n\nInvalid JSON received by the server.\n\n```js\nimport { ParseError } from '@atmaca/errors'\n\nthrow new ParseError('Unexpected token at position 42')\n// REST: 400, JSON-RPC: -32700\n```\n\n#### InvalidRequestError\n\nThe JSON sent is not a valid Request object.\n\n```js\nimport { InvalidRequestError } from '@atmaca/errors'\n\nthrow new InvalidRequestError('Missing \"method\" field')\n// REST: 400, JSON-RPC: -32600\n```\n\n#### InvalidParamsError\n\nInvalid method parameters.\n\n```js\nimport { InvalidParamsError } from '@atmaca/errors'\n\nthrow new InvalidParamsError('Parameter \"userId\" must be a number')\n// REST: 400, JSON-RPC: -32602\n```\n\n#### InternalError\n\nInternal JSON-RPC error.\n\n```js\nimport { InternalError } from '@atmaca/errors'\n\nthrow new InternalError('database connection', originalError)\n// REST: 500, JSON-RPC: -32603\n```\n\n---\n\n### REST-Compliant Errors\n\n#### Client Errors (4xx)\n\n##### ValidationError\n\nInput validation failed.\n\n```js\nimport { ValidationError } from '@atmaca/errors'\n\nthrow new ValidationError('email', 'invalid-email', 'must be a valid email address')\n// REST: 400, JSON-RPC: -32001\n\n// Properties\nerror.field      // 'email'\nerror.constraint // 'must be a valid email address'\n```\n\n##### NotFoundError\n\nResource not found.\n\n```js\nimport { NotFoundError } from '@atmaca/errors'\n\nthrow new NotFoundError('User', { userId: 123 })\n// REST: 404, JSON-RPC: -32002\n\n// Properties\nerror.entity   // 'User'\nerror.reason   // 'user_not_found'\nerror.metadata // { userId: 123 }\n```\n\n##### NotAuthorizedError\n\nAuthentication required.\n\n```js\nimport { NotAuthorizedError } from '@atmaca/errors'\n\nthrow new NotAuthorizedError('User', 'token expired', { tokenId: 'abc123' })\n// REST: 401, JSON-RPC: -32005\n```\n\n##### ForbiddenError\n\nAction forbidden for user.\n\n```js\nimport { ForbiddenError } from '@atmaca/errors'\n\nthrow new ForbiddenError('User', 'delete account', { userId: 123 })\n// REST: 403, JSON-RPC: -32004\n\n// Properties\nerror.entity // 'User'\nerror.action // 'delete account'\n```\n\n##### ConflictError\n\nResource conflict (e.g., duplicate entry).\n\n```js\nimport { ConflictError } from '@atmaca/errors'\n\nthrow new ConflictError('User', 'email already exists', { email: 'user@example.com' })\n// REST: 409, JSON-RPC: -32003\n\n// Properties\nerror.entity         // 'User'\nerror.conflictReason // 'email already exists'\n```\n\n##### PreconditionFailedError\n\nPrecondition not met.\n\n```js\nimport { PreconditionFailedError } from '@atmaca/errors'\n\nthrow new PreconditionFailedError('If-Match header must match current ETag')\n// REST: 412, JSON-RPC: -32007\n\n// Properties\nerror.condition // 'If-Match header must match current ETag'\n```\n\n##### PayloadTooLargeError\n\nRequest body too large.\n\n```js\nimport { PayloadTooLargeError } from '@atmaca/errors'\n\nthrow new PayloadTooLargeError(5242880, 1048576) // 5MB vs 1MB limit\n// REST: 413, JSON-RPC: -32009\n\n// Properties\nerror.size    // 5242880\nerror.maxSize // 1048576\n```\n\n##### UnsupportedMediaTypeError\n\nContent type not supported.\n\n```js\nimport { UnsupportedMediaTypeError } from '@atmaca/errors'\n\nthrow new UnsupportedMediaTypeError('text/xml', ['application/json', 'application/x-www-form-urlencoded'])\n// REST: 415, JSON-RPC: -32008\n\n// Properties\nerror.providedType   // 'text/xml'\nerror.supportedTypes // ['application/json', 'application/x-www-form-urlencoded']\n```\n\n##### UnprocessableEntityError\n\nSemantic validation error.\n\n```js\nimport { UnprocessableEntityError } from '@atmaca/errors'\n\nthrow new UnprocessableEntityError('invalid_date_range', 'Start date must be before end date')\n// REST: 422, JSON-RPC: -32006\n```\n\n##### RateLimitExceededError\n\nToo many requests.\n\n```js\nimport { RateLimitExceededError } from '@atmaca/errors'\n\nthrow new RateLimitExceededError(100, 60000, 30) // 100 requests per minute, retry after 30s\n// REST: 429, JSON-RPC: -32010\n\n// Properties\nerror.limit      // 100\nerror.windowMs   // 60000\nerror.retryAfter // 30\n```\n\n##### ResourceExhaustedError\n\nResource limit reached.\n\n```js\nimport { ResourceExhaustedError } from '@atmaca/errors'\n\nthrow new ResourceExhaustedError('database connections', 100, { current: 100 })\n// REST: 429, JSON-RPC: -32011\n\n// Properties\nerror.resource // 'database connections'\nerror.limit    // 100\n```\n\n##### BusinessRuleError\n\nBusiness rule violation.\n\n```js\nimport { BusinessRuleError } from '@atmaca/errors'\n\nthrow new BusinessRuleError('minimum_order_value', 'Order total must be at least $10', { total: 5.99 })\n// REST: 409, JSON-RPC: -32017\n\n// Properties\nerror.rule        // 'minimum_order_value'\nerror.description // 'Order total must be at least $10'\n```\n\n##### GoneError\n\nResource permanently removed.\n\n```js\nimport { GoneError } from '@atmaca/errors'\n\nthrow new GoneError('API v1 endpoint', { deprecatedSince: '2024-01-01' })\n// REST: 410, JSON-RPC: -32019\n\n// Properties\nerror.resource // 'API v1 endpoint'\n```\n\n#### Server Errors (5xx)\n\n##### FunctionExecutionError\n\nHandler execution failed.\n\n```js\nimport { FunctionExecutionError } from '@atmaca/errors'\n\nthrow new FunctionExecutionError('getUser', 'handler', originalError, { userId: 123 })\n// REST: 500, JSON-RPC: -32015\n\n// Properties\nerror.fnName        // 'getUser'\nerror.phase         // 'handler'\nerror.originalError // originalError object\n```\n\n##### BadGatewayError\n\nUpstream service error.\n\n```js\nimport { BadGatewayError } from '@atmaca/errors'\n\nthrow new BadGatewayError('payment-service', upstreamError, { requestId: 'req-123' })\n// REST: 502, JSON-RPC: -32012\n\n// Properties\nerror.upstream      // 'payment-service'\nerror.upstreamError // upstreamError object\n```\n\n##### ServiceUnavailableError\n\nService temporarily unavailable.\n\n```js\nimport { ServiceUnavailableError } from '@atmaca/errors'\n\nthrow new ServiceUnavailableError('database', 60) // retry after 60 seconds\n// REST: 503, JSON-RPC: -32013\n\n// Properties\nerror.service    // 'database'\nerror.retryAfter // 60\n```\n\n##### DependencyError\n\nRequired dependency unavailable.\n\n```js\nimport { DependencyError } from '@atmaca/errors'\n\nthrow new DependencyError('processPayment', 'stripe-api', { reason: 'connection timeout' })\n// REST: 503, JSON-RPC: -32014\n\n// Properties\nerror.fnName     // 'processPayment'\nerror.dependency // 'stripe-api'\n```\n\n##### NotImplementedError\n\nFeature not yet implemented.\n\n```js\nimport { NotImplementedError } from '@atmaca/errors'\n\nthrow new NotImplementedError('bulk export', { requestedBy: 'user-123' })\n// REST: 501, JSON-RPC: -32016\n\n// Properties\nerror.feature // 'bulk export'\n```\n\n##### TimeoutError\n\nOperation timed out.\n\n```js\nimport { TimeoutError } from '@atmaca/errors'\n\nthrow new TimeoutError('database query', 30000, { query: 'SELECT * FROM users' })\n// REST: 504, JSON-RPC: -32018\n\n// Properties\nerror.operation // 'database query'\nerror.timeoutMs // 30000\n```\n\n---\n\n### Special Errors\n\n#### MethodNotFoundError\n\nMethod/function does not exist (extends NotFoundError).\n\n```js\nimport { MethodNotFoundError } from '@atmaca/errors'\n\nthrow new MethodNotFoundError('nonExistentFunction')\n// REST: 404, JSON-RPC: -32601\n```\n\n#### TextErrorResponse\n\nGeneric error response with custom status code.\n\n```js\nimport { TextErrorResponse } from '@atmaca/errors'\n\nthrow new TextErrorResponse('Something went wrong', 500, originalError)\n// REST: 500 (configurable)\n\n// Properties\nerror.name     // 'TextErrorResponse'\nerror.restCode // 500 (or custom code)\n```\n\n---\n\n## Complete Error Reference Table\n\n| Error Class | REST Code | JSON-RPC Code | Description |\n|-------------|-----------|---------------|-------------|\n| **JSON-RPC Specific** ||||\n| `ParseError` | 400 | -32700 | Invalid JSON received by server |\n| `InvalidRequestError` | 400 | -32600 | Invalid JSON-RPC Request object |\n| `MethodNotFoundError` | 404 | -32601 | Method/function does not exist |\n| `InvalidParamsError` | 400 | -32602 | Invalid method parameters |\n| `InternalError` | 500 | -32603 | Internal JSON-RPC error |\n| **Client Errors (4xx)** ||||\n| `ValidationError` | 400 | -32001 | Input validation failed |\n| `NotFoundError` | 404 | -32002 | Resource not found |\n| `NotAuthorizedError` | 401 | -32005 | Authentication required |\n| `ForbiddenError` | 403 | -32004 | Action forbidden for user |\n| `ConflictError` | 409 | -32003 | Resource conflict (e.g., duplicate) |\n| `PreconditionFailedError` | 412 | -32007 | Precondition not met |\n| `PayloadTooLargeError` | 413 | -32009 | Request body too large |\n| `UnsupportedMediaTypeError` | 415 | -32008 | Content type not supported |\n| `UnprocessableEntityError` | 422 | -32006 | Semantic validation error |\n| `RateLimitExceededError` | 429 | -32010 | Too many requests |\n| `ResourceExhaustedError` | 429 | -32011 | Resource limit reached |\n| `BusinessRuleError` | 409 | -32017 | Business rule violation |\n| `GoneError` | 410 | -32019 | Resource permanently removed |\n| **Server Errors (5xx)** ||||\n| `FunctionExecutionError` | 500 | -32015 | Handler execution failed |\n| `InternalError` | 500 | -32603 | Internal error |\n| `NotImplementedError` | 501 | -32016 | Feature not yet implemented |\n| `BadGatewayError` | 502 | -32012 | Upstream service error |\n| `ServiceUnavailableError` | 503 | -32013 | Service temporarily unavailable |\n| `DependencyError` | 503 | -32014 | Required dependency unavailable |\n| `TimeoutError` | 504 | -32018 | Operation timed out |\n\n---\n\n## Usage Examples\n\n### REST API Error Handling\n\n```js\nimport express from 'express'\nimport { NotFoundError, ValidationError, NotAuthorizedError } from '@atmaca/errors'\n\nconst app = express()\n\napp.get('/users/{id}', async (req, res) => {\n  try {\n    const user = await db.users.findById(req.params.id)\n\n    if (!user) {\n      throw new NotFoundError('User', { userId: req.params.id })\n    }\n\n    if (!req.user || req.user.id !== user.id) {\n      throw new NotAuthorizedError('User', 'can only view own profile')\n    }\n\n    res.json(user)\n  } catch (error) {\n    // Use the REST code from the error\n    res.status(error.restCode || 500).json({\n      error: {\n        name: error.name,\n        reason: error.reason,\n        message: error.message,\n        metadata: error.metadata\n      }\n    })\n  }\n})\n```\n\n### JSON-RPC Service Error Handling\n\n```js\nimport {\n  ParseError,\n  InvalidRequestError,\n  MethodNotFoundError,\n  InvalidParamsError\n} from '@atmaca/errors'\n\nasync function handleJsonRpc(request) {\n  try {\n    // Parse JSON\n    let parsed\n    try {\n      parsed = JSON.parse(request.body)\n    } catch (e) {\n      throw new ParseError('Invalid JSON format')\n    }\n\n    // Validate request structure\n    if (!parsed.jsonrpc || !parsed.method) {\n      throw new InvalidRequestError('Missing required fields')\n    }\n\n    // Check method exists\n    if (!methods[parsed.method]) {\n      throw new MethodNotFoundError(parsed.method)\n    }\n\n    // Execute method\n    const result = await methods[parsed.method](parsed.params)\n\n    return {\n      jsonrpc: '2.0',\n      result,\n      id: parsed.id\n    }\n  } catch (error) {\n    // Use the JSON-RPC code from the error\n    return {\n      jsonrpc: '2.0',\n      error: {\n        code: error.jsonRpcCode || -32603,\n        message: error.message,\n        data: error.metadata\n      },\n      id: parsed?.id || null\n    }\n  }\n}\n```\n\n## Best Practices\n\n### 1. Always Include Metadata\n\n```js\n// Good - includes context\nthrow new NotFoundError('User', { userId: 123, requestId: 'req-456' })\n\n// Avoid - missing context\nthrow new NotFoundError('User')\n```\n\n### 2. Use Specific Error Classes\n\n```js\n// Good - specific error\nthrow new ConflictError('User', 'email already exists', { email: 'user@example.com' })\n\n// Avoid - generic error\nthrow new Error('Conflict: email already exists')\n```\n\n### 3. Preserve Original Errors\n\n```js\n// Good - includes original error\ntry {\n  await upstream.call()\n} catch (err) {\n  throw new BadGatewayError('payment-service', err)\n}\n\n// Avoid - loses original context\ntry {\n  await upstream.call()\n} catch (err) {\n  throw new BadGatewayError('payment-service')\n}\n```\n\n### 4. Use Machine-Readable Reason Codes\n\n```js\n// The reason property is automatically generated for most errors\nconst error = new NotFoundError('User')\nconsole.log(error.reason) // 'user_not_found'\n\nconst error2 = new ConflictError('Email Address', 'already in use')\nconsole.log(error2.reason) // 'email_address_conflict'\n```\n\n---\n\n## Protocol Bridging\n\nUse errors seamlessly across different protocols:\n\n```js\nimport { NotFoundError } from '@atmaca/errors'\n\nconst error = new NotFoundError('Resource', { id: 123 })\n\n// REST response\nres.status(error.restCode).json({\n  error: {\n    message: error.message,\n    reason: error.reason,\n    metadata: error.metadata\n  }\n})\n\n// JSON-RPC response\nres.json({\n  jsonrpc: '2.0',\n  error: {\n    code: error.jsonRpcCode,\n    message: error.message,\n    data: error.metadata\n  },\n  id: request.id\n})\n\n// GraphQL response\nthrow new GraphQLError(error.message, {\n  extensions: {\n    code: error.reason.toUpperCase(),\n    http: { status: error.restCode },\n    metadata: error.metadata\n  }\n})\n```\n\n---\n\n## TypeScript Support\n\nTypeScript declarations are included:\n\n```typescript\nimport { NotFoundError, ValidationError, RuntimeError } from '@atmaca/errors'\n\nfunction handleError(error: RuntimeError): void {\n  console.log(error.name)        // string\n  console.log(error.reason)      // string\n  console.log(error.message)     // string\n  console.log(error.restCode)    // number\n  console.log(error.jsonRpcCode) // number\n  console.log(error.metadata)    // any\n}\n```\n\n---\n\n## License\n\nMIT License\n","readmeFilename":"README.MD","_rev":"1-0a886f845f559b4da2c0eea1f1d2ca51"}