{"_id":"@cap-sf-sdk/sf-normalizer","_rev":"2-64afb5b1d25deec03be8f3243f12febc","name":"@cap-sf-sdk/sf-normalizer","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@cap-sf-sdk/sf-normalizer","version":"1.0.0","keywords":["normalizer","successfactors","cap"],"author":{"name":"Samad & Soultan Hatsijev"},"license":"MIT","_id":"@cap-sf-sdk/sf-normalizer@1.0.0","maintainers":[{"name":"samadh90","email":"s.hatsijev@hotmail.com"}],"dist":{"shasum":"70cad46961c26fb04c836ca2fb420b043d2fb337","tarball":"https://registry.npmjs.org/@cap-sf-sdk/sf-normalizer/-/sf-normalizer-1.0.0.tgz","fileCount":12,"integrity":"sha512-oQB6aUt1vwPtkj6oE85OIs9S1AbaKieDRqc37TXVhBg3lwZrkppHBSrJ2gpbgVID92EjUAgd5IhoAqmototgrw==","signatures":[{"sig":"MEYCIQDYyckYol5KDqlmugwwosgoLE8KrC2/jTMFDczDuTvkWQIhAJyHbkc24f/JmaktxXkBj0kFUwte99Oa9v/2/eruOoLm","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17142},"main":"dist/sf-normalizer/index.js","types":"dist/sf-normalizer/index.d.ts","module":"dist/sf-normalizer/index.mjs","gitHead":"33aafe2e224307930d52361ffe973ca01bfcf8a9","scripts":{"docs":"cd ../.. && npm run docs","test":"cd ../.. && npx jest --selectProjects sf-normalizer","build":"tsup src/index.ts --dts","clean":"rimraf dist"},"_npmUser":{"name":"samadh90","email":"s.hatsijev@hotmail.com"},"_npmVersion":"10.9.0","description":"Normalizes SuccessFactors OData v2 JSON responses into clean JavaScript objects.","directories":{},"_nodeVersion":"22.12.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{},"_npmOperationalInternal":{"tmp":"tmp/sf-normalizer_1.0.0_1759706129494_0.2511381758120945","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@cap-sf-sdk/sf-normalizer","version":"1.0.1","description":"Normalizes SuccessFactors OData v2 JSON responses into clean JavaScript objects.","main":"dist/sf-normalizer/index.js","module":"dist/sf-normalizer/index.mjs","types":"dist/sf-normalizer/index.d.ts","scripts":{"build":"tsup src/index.ts --dts","clean":"rimraf dist","docs":"cd ../.. && npm run docs","test":"cd ../.. && npx jest --selectProjects sf-normalizer"},"keywords":["normalizer","successfactors","cap"],"author":{"name":"Samad & Soultan Hatsijev"},"license":"MIT","dependencies":{},"devDependencies":{},"publishConfig":{"access":"public"},"_id":"@cap-sf-sdk/sf-normalizer@1.0.1","gitHead":"4a7589c4edb3e1c588b6bdc76566013a17ab7921","_nodeVersion":"22.12.0","_npmVersion":"10.9.0","dist":{"integrity":"sha512-hsBFQwp7Lwqc3edFmXjK2Ayhpl3Rd33kEz4EfNFzE7N0oDyEQ7Qa3nCbA2WOKA/aqa8MSvJFK03W6Nb8P9c8vA==","shasum":"241dd4b16118cc27f0dfb0b8a970693eb0c26ba8","tarball":"https://registry.npmjs.org/@cap-sf-sdk/sf-normalizer/-/sf-normalizer-1.0.1.tgz","fileCount":15,"unpackedSize":26396,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDZyYGRDCviBuxTJdoUBuXECX/FyWSx634DTl22tBpZMwIgNhAWdPxrRaj43ldxnBIHRaDGZMNzn9TshwWhorEXyKg="}]},"_npmUser":{"name":"samadh90","email":"s.hatsijev@hotmail.com"},"directories":{},"maintainers":[{"name":"samadh90","email":"s.hatsijev@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sf-normalizer_1.0.1_1759958233916_0.9400547074961871"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-05T23:15:29.444Z","modified":"2025-10-08T21:17:14.285Z","1.0.0":"2025-10-05T23:15:29.717Z","1.0.1":"2025-10-08T21:17:14.093Z"},"author":{"name":"Samad & Soultan Hatsijev"},"license":"MIT","keywords":["normalizer","successfactors","cap"],"description":"Normalizes SuccessFactors OData v2 JSON responses into clean JavaScript objects.","maintainers":[{"name":"samadh90","email":"s.hatsijev@hotmail.com"}],"readme":"# @cap-sf-sdk/sf-normalizer\r\n\r\n> Normalize SuccessFactors OData v2 JSON responses into clean JavaScript objects.\r\n\r\nPart of the [CAP SuccessFactors SDK](../../README.md) monorepo.\r\n\r\n## 🚀 Installation\r\n\r\n```bash\r\n# Install this package individually\r\nnpm install @cap-sf-sdk/sf-normalizer\r\n\r\n# Or install the complete SDK\r\nnpm install @cap-sf-sdk/core\r\n```\r\n\r\n## 📖 Overview\r\n\r\nThe SF Normalizer handles the complexities of SuccessFactors OData v2 responses, converting them into clean, usable JavaScript objects. It automatically handles:\r\n\r\n- **Response unwrapping**: Removes OData `d` and `d.results` wrappers\r\n- **Date parsing**: Converts `/Date(timestamp)/` strings to JavaScript Date objects\r\n- **Metadata cleanup**: Removes `__metadata` properties\r\n- **Nested processing**: Recursively processes nested objects and arrays\r\n- **Request serialization**: Prepares JavaScript objects for SuccessFactors APIs\r\n\r\n## 🧩 Usage\r\n\r\n### Response Normalization\r\n\r\n```typescript\r\nimport { normalizeSFResponse } from '@cap-sf-sdk/sf-normalizer'\r\n\r\n// SuccessFactors single entity response\r\nconst sfSingleResponse = {\r\n  d: {\r\n    externalCode: 'EMP001',\r\n    startDate: '/Date(1704067200000)/',\r\n    endDate: '/Date(1735689600000)/',\r\n    status: 'A',\r\n    __metadata: {\r\n      uri: \"https://api.successfactors.com/odata/v2/PerPerson('EMP001')\",\r\n      type: 'SFOData.PerPerson',\r\n    },\r\n  },\r\n}\r\n\r\nconst normalized = normalizeSFResponse(sfSingleResponse)\r\nconsole.log(normalized)\r\n// Result: {\r\n//   externalCode: 'EMP001',\r\n//   startDate: Date('2024-01-01T00:00:00.000Z'),\r\n//   endDate: Date('2024-12-31T00:00:00.000Z'),\r\n//   status: 'A'\r\n// }\r\n\r\n// SuccessFactors collection response\r\nconst sfCollectionResponse = {\r\n  d: {\r\n    results: [\r\n      {\r\n        externalCode: 'EMP001',\r\n        startDate: '/Date(1704067200000)/',\r\n        __metadata: {\r\n          /* ... */\r\n        },\r\n      },\r\n      {\r\n        externalCode: 'EMP002',\r\n        startDate: '/Date(1706745600000)/',\r\n        __metadata: {\r\n          /* ... */\r\n        },\r\n      },\r\n    ],\r\n  },\r\n}\r\n\r\nconst normalizedCollection = normalizeSFResponse(sfCollectionResponse)\r\nconsole.log(normalizedCollection)\r\n// Result: [\r\n//   { externalCode: 'EMP001', startDate: Date('2024-01-01') },\r\n//   { externalCode: 'EMP002', startDate: Date('2024-02-01') }\r\n// ]\r\n```\r\n\r\n### Request Serialization\r\n\r\n```typescript\r\nimport { serializeSFRequest } from '@cap-sf-sdk/sf-normalizer'\r\n\r\n// JavaScript object with Date objects\r\nconst payload = {\r\n  externalCode: 'EMP001',\r\n  startDate: new Date('2024-01-01'),\r\n  endDate: new Date('2024-12-31'),\r\n  personalInfo: {\r\n    birthDate: new Date('1990-05-15'),\r\n  },\r\n}\r\n\r\nconst serialized = serializeSFRequest(payload)\r\nconsole.log(serialized)\r\n// Result: {\r\n//   externalCode: 'EMP001',\r\n//   startDate: '/Date(1704067200000)/',\r\n//   endDate: '/Date(1735689600000)/',\r\n//   personalInfo: {\r\n//     birthDate: '/Date(642902400000)/'\r\n//   }\r\n// }\r\n```\r\n\r\n### Complete CAP Integration Example\r\n\r\n```typescript\r\nimport { normalizeSFResponse, serializeSFRequest } from '@cap-sf-sdk/sf-normalizer'\r\nimport { cqnToOData } from '@cap-sf-sdk/odata-transformer'\r\n\r\n// In your CAP service\r\nthis.on('READ', 'Employees', async (req) => {\r\n  // Transform CAP query to OData\r\n  const odataQuery = cqnToOData(req.query)\r\n\r\n  // Fetch from SuccessFactors\r\n  const response = await fetch(`https://api.successfactors.com/odata/v2/PerPerson?${odataQuery}`)\r\n  const rawData = await response.json()\r\n\r\n  // Normalize the response\r\n  const employees = normalizeSFResponse(rawData)\r\n\r\n  return employees\r\n})\r\n\r\nthis.on(['CREATE', 'UPDATE'], 'Employees', async (req) => {\r\n  // Serialize for SuccessFactors\r\n  const sfPayload = serializeSFRequest(req.data)\r\n\r\n  // Send to SuccessFactors\r\n  const response = await fetch('https://api.successfactors.com/odata/v2/PerPerson', {\r\n    method: 'POST',\r\n    headers: { 'Content-Type': 'application/json' },\r\n    body: JSON.stringify(sfPayload),\r\n  })\r\n\r\n  const result = await response.json()\r\n  return normalizeSFResponse(result)\r\n})\r\n```\r\n\r\n## 🔧 API Reference\r\n\r\n### `normalizeSFResponse(response)`\r\n\r\nNormalizes a SuccessFactors OData v2 response into clean JavaScript objects.\r\n\r\n**Parameters:**\r\n\r\n- `response: any` - Raw SuccessFactors response with `d` or `d.results` wrapper\r\n\r\n**Returns:** `any` - Normalized JavaScript object or array\r\n\r\n**Features:**\r\n\r\n- Unwraps `d` and `d.results` containers\r\n- Converts SAP date strings (`/Date(timestamp)/`) to Date objects\r\n- Removes `__metadata` properties\r\n- Recursively processes nested objects and arrays\r\n\r\n### `serializeSFRequest(data)`\r\n\r\nSerializes JavaScript objects for SuccessFactors OData v2 API requests.\r\n\r\n**Parameters:**\r\n\r\n- `data: any` - JavaScript object or array to serialize\r\n\r\n**Returns:** `any` - SuccessFactors-compatible payload\r\n\r\n**Features:**\r\n\r\n- Converts Date objects to SAP date format (`/Date(timestamp)/`)\r\n- Preserves all other data types and structures\r\n- Recursively processes nested objects and arrays\r\n\r\n## 🛠️ Utility Functions\r\n\r\nFor advanced use cases, you can access individual utility functions:\r\n\r\n```typescript\r\nimport { utils } from '@cap-sf-sdk/sf-normalizer'\r\n\r\n// Date utilities\r\nconst date = utils.parseSapDate('/Date(1704067200000)/') // Returns Date object\r\nconst sapDate = utils.toSapDate(new Date('2024-01-01')) // Returns '/Date(1704067200000)/'\r\nconst isSapDate = utils.isSapDateString('/Date(123456)/') // Returns true\r\n\r\n// Object utilities\r\nconst normalized = utils.normalizeObject(rawObject)\r\nconst serialized = utils.serializeObject(jsObject)\r\nconst data = utils.extractSFData(sfResponse)\r\n```\r\n\r\n## 🏗️ Project Structure\r\n\r\n```\r\nsrc/\r\n├── index.ts              # Main entry point\r\n├── types.ts              # TypeScript type definitions\r\n├── normalizers/          # Response normalization\r\n│   └── normalizeSFResponse.ts\r\n├── serializers/          # Request serialization\r\n│   └── serializeSFRequest.ts\r\n└── utils/                # Utility functions\r\n    ├── index.ts         # Utils entry point\r\n    ├── dateUtils.ts     # SAP date handling\r\n    └── objectUtils.ts   # Object processing\r\n```\r\n\r\n## 🧪 Testing\r\n\r\n```bash\r\n# Run tests for this package\r\nnpm test\r\n\r\n# Run tests from package directory\r\ncd packages/sf-normalizer\r\nnpm test\r\n\r\n# Coverage report\r\nnpm run test:coverage\r\n```\r\n\r\n## 📚 Related Packages\r\n\r\n- [`@cap-sf-sdk/odata-transformer`](../odata-transformer) - Transform CAP queries to OData\r\n- [`@cap-sf-sdk/core`](../core) - Complete SDK with all packages\r\n\r\n## 🤝 Contributing\r\n\r\nSee the [main repository](../../README.md#contributing) for contribution guidelines.\r\n\r\n## 📄 License\r\n\r\nMIT - see [LICENSE](../../LICENSE) for details.\r\n","readmeFilename":"README.md"}