{"_id":"@chuli-dev/value-objects","_rev":"5-e2c5c50ac5e2afe1bf2fc6d4cad18b56","name":"@chuli-dev/value-objects","dist-tags":{"latest":"0.5.0"},"versions":{"0.1.0":{"name":"@chuli-dev/value-objects","version":"0.1.0","keywords":["value-objects","ddd","domain","typescript"],"author":{"name":"chuli-dev"},"license":"MIT","_id":"@chuli-dev/value-objects@0.1.0","maintainers":[{"name":"chuli-dev","email":"tomasantunez.dev@gmail.com"}],"homepage":"https://github.com/TomasAntunez/chuli-dev-libs/blob/main/libs/value-objects/README.md","bugs":{"url":"https://github.com/TomasAntunez/chuli-dev-libs/issues"},"dist":{"shasum":"58116b4583e797101783e6a4dc4bf0b5acaa38ca","tarball":"https://registry.npmjs.org/@chuli-dev/value-objects/-/value-objects-0.1.0.tgz","fileCount":39,"integrity":"sha512-f26FTIqBb8ERqQ/EUHkNuGVoHAIWX03lpPvU73Gkr4Ptd//2d5D/XhcC45ewrynuytAQ+aNdoVZpltbN6VUbCQ==","signatures":[{"sig":"MEYCIQDI9egL/WxIru6RVy2SrTXZupeUXhCu2Rjf07KGgEWwqQIhAPTYRi06J7mdOCStWfkgzk9rX014FBJ0ySBZ07uKHNor","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":32650},"type":"module","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"14c8a5744ef069ceb70a6a63d7b29da9e76a6852","scripts":{"build":"npm run clean && tsc -p tsconfig.json","clean":"rimraf dist","prepare":"npm run build","lint:check":"eslint . --max-warnings 0"},"_npmUser":{"name":"chuli-dev","email":"tomasantunez.dev@gmail.com"},"repository":{"url":"git+https://github.com/TomasAntunez/chuli-dev-libs.git","type":"git","directory":"libs/value-objects"},"_npmVersion":"11.11.0","description":"Value object base class and primitives for DDD","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.0.0","globals":">=16","@eslint/js":"^9.0.0","eslint-plugin-n":"^17.0.0","@chuli-dev/errors":"*","typescript-eslint":"^8.0.0","@chuli-dev/eslint-config":"*","@chuli-dev/typescript-config":"*","eslint-plugin-unused-imports":"^4.0.0","eslint-plugin-simple-import-sort":"^12.0.0"},"peerDependencies":{"@chuli-dev/errors":"*"},"_npmOperationalInternal":{"tmp":"tmp/value-objects_0.1.0_1778291640529_0.5419860763455","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@chuli-dev/value-objects","version":"0.2.0","keywords":["value-objects","ddd","domain","typescript"],"author":{"name":"chuli-dev"},"license":"MIT","_id":"@chuli-dev/value-objects@0.2.0","maintainers":[{"name":"chuli-dev","email":"tomasantunez.dev@gmail.com"}],"homepage":"https://github.com/TomasAntunez/chuli-dev-libs/blob/main/libs/value-objects/README.md","bugs":{"url":"https://github.com/TomasAntunez/chuli-dev-libs/issues"},"dist":{"shasum":"49137049a7e36651db47cd0edf753a896a6e0e82","tarball":"https://registry.npmjs.org/@chuli-dev/value-objects/-/value-objects-0.2.0.tgz","fileCount":39,"integrity":"sha512-j96V9oPz55MgbjT+8F4UkEN7nxYVg5pQSQwL6SW+sXQdx0DIbT+OoYhEvl+Zh97ejdbrus7NWHw46wGvxGjjCw==","signatures":[{"sig":"MEYCIQCEDVtd6tehKaBI6Saytr946RCK6EnrZk5pd1nHXl1hrwIhALPADZa5X46aFckjyJQzSWaSSkBngcb9XWDRugPH20bc","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":32186},"type":"module","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"4001cd29ea88a636f0ea129c49567784039286ae","scripts":{"build":"npm run clean && tsc -p tsconfig.json","clean":"rimraf dist","prepare":"npm run build","lint:check":"eslint . --max-warnings 0"},"_npmUser":{"name":"chuli-dev","email":"tomasantunez.dev@gmail.com"},"repository":{"url":"git+https://github.com/TomasAntunez/chuli-dev-libs.git","type":"git","directory":"libs/value-objects"},"_npmVersion":"11.11.0","description":"Value object base class and primitives for DDD","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.0.0","globals":">=16","@eslint/js":"^9.0.0","eslint-plugin-n":"^17.0.0","@chuli-dev/errors":"*","typescript-eslint":"^8.0.0","@chuli-dev/eslint-config":"*","@chuli-dev/typescript-config":"*","eslint-plugin-unused-imports":"^4.0.0","eslint-plugin-simple-import-sort":"^12.0.0"},"peerDependencies":{"@chuli-dev/errors":"*"},"_npmOperationalInternal":{"tmp":"tmp/value-objects_0.2.0_1778350897813_0.7384097075260776","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@chuli-dev/value-objects","version":"0.3.0","keywords":["value-objects","ddd","domain","typescript"],"author":{"name":"chuli-dev"},"license":"MIT","_id":"@chuli-dev/value-objects@0.3.0","maintainers":[{"name":"chuli-dev","email":"tomasantunez.dev@gmail.com"}],"homepage":"https://github.com/TomasAntunez/chuli-dev-libs/tree/main/libs/value-objects","bugs":{"url":"https://github.com/TomasAntunez/chuli-dev-libs/issues"},"dist":{"shasum":"46b321236dc7a2eabd836262574389556f686297","tarball":"https://registry.npmjs.org/@chuli-dev/value-objects/-/value-objects-0.3.0.tgz","fileCount":77,"integrity":"sha512-TLT7eaLgXCCi2r/hjsUQ0R04OfAsKDtrAWSxBXQtHSE2VMZv351oIVgPZVe+L0YSai64PyRy2u59gR00JxU8lw==","signatures":[{"sig":"MEQCIBzFYdNAk83PoIBEsmWokTGDBkLiCQELCw5DXoqz3pHOAiA98AfcUaxMSW6vFEIgIg214w4wm02tNbfaBCT+hTU/ig==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":61564},"type":"module","exports":{".":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.js"}}},"gitHead":"d76baca19f61df1fd96bc8a1fd98819336ed9b50","scripts":{"build":"npm run clean && npm run build:esm && npm run build:cjs && npm run build:pkg-jsons","clean":"rimraf dist","prepare":"npm run build","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","lint:check":"eslint . --max-warnings 0","build:pkg-jsons":"tsx ../../apps/cli/src/main.ts write-dist-package-jsons"},"_npmUser":{"name":"chuli-dev","email":"tomasantunez.dev@gmail.com"},"repository":{"url":"git+https://github.com/TomasAntunez/chuli-dev-libs.git","type":"git","directory":"libs/value-objects"},"_npmVersion":"11.11.0","description":"Value object base class and primitives for DDD","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.0.0","globals":">=16","@eslint/js":"^9.0.0","eslint-plugin-n":"^17.0.0","@chuli-dev/errors":"*","typescript-eslint":"^8.0.0","@chuli-dev/eslint-config":"*","@chuli-dev/typescript-config":"*","eslint-plugin-unused-imports":"^4.0.0","eslint-plugin-simple-import-sort":"^12.0.0"},"peerDependencies":{"@chuli-dev/errors":"*"},"_npmOperationalInternal":{"tmp":"tmp/value-objects_0.3.0_1778366591752_0.7718709087562339","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@chuli-dev/value-objects","version":"0.4.0","keywords":["value-objects","ddd","domain","typescript"],"author":{"name":"chuli-dev"},"license":"MIT","_id":"@chuli-dev/value-objects@0.4.0","maintainers":[{"name":"chuli-dev","email":"tomasantunez.dev@gmail.com"}],"homepage":"https://github.com/TomasAntunez/chuli-dev-libs/tree/main/libs/value-objects","bugs":{"url":"https://github.com/TomasAntunez/chuli-dev-libs/issues"},"dist":{"shasum":"479ce9eb1ccf3a52431889884e5be7edb21ccdf9","tarball":"https://registry.npmjs.org/@chuli-dev/value-objects/-/value-objects-0.4.0.tgz","fileCount":77,"integrity":"sha512-7wfcbzuUPBoODR4iKaJ21LGYweeWaeTOnuWOabCz3WAqumvwiO35tk4E2y4YIGTR2fNX2djIVBnNb0Gs5z8R8Q==","signatures":[{"sig":"MEYCIQDh7Zo8dG1vkTFgcMoNiXE9CqeC+QNZREKB4l1jNfpNrQIhAOOlZHcNBmRb7+ZAtLSZ4tfSxgfD9eStiGlWdfDq830v","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":61308},"type":"module","exports":{".":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.js"}}},"gitHead":"dd576c8ddcb583c36c8fef7dbc189269ee890dc0","scripts":{"lint:check":"eslint . --max-warnings 0"},"_npmUser":{"name":"chuli-dev","email":"tomasantunez.dev@gmail.com"},"repository":{"url":"git+https://github.com/TomasAntunez/chuli-dev-libs.git","type":"git","directory":"libs/value-objects"},"_npmVersion":"11.12.1","description":"Value object base class and primitives for DDD","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.0.0","globals":">=16","@eslint/js":"^9.0.0","eslint-plugin-n":"^17.0.0","@chuli-dev/errors":"*","typescript-eslint":"^8.0.0","@chuli-dev/eslint-config":"*","@chuli-dev/typescript-config":"*","eslint-plugin-unused-imports":"^4.0.0","eslint-plugin-simple-import-sort":"^12.0.0"},"peerDependencies":{"@chuli-dev/errors":"*"},"_npmOperationalInternal":{"tmp":"tmp/value-objects_0.4.0_1778968189823_0.5599584744200685","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@chuli-dev/value-objects","version":"0.5.0","type":"module","description":"Value object base class and primitives for DDD","keywords":["value-objects","ddd","domain","typescript"],"author":{"name":"chuli-dev"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/TomasAntunez/chuli-dev-libs.git","directory":"libs/value-objects"},"homepage":"https://github.com/TomasAntunez/chuli-dev-libs/tree/main/libs/value-objects","bugs":{"url":"https://github.com/TomasAntunez/chuli-dev-libs/issues"},"publishConfig":{"access":"public"},"scripts":{"lint:check":"eslint . --max-warnings 0"},"exports":{".":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.js"}}},"peerDependencies":{"@chuli-dev/errors":"*"},"devDependencies":{"@chuli-dev/errors":"*","@chuli-dev/eslint-config":"*","@chuli-dev/typescript-config":"*","@eslint/js":"^9.0.0","eslint":"^9.0.0","eslint-plugin-n":"^17.0.0","eslint-plugin-simple-import-sort":"^12.0.0","eslint-plugin-unused-imports":"^4.0.0","globals":">=16","typescript-eslint":"^8.0.0"},"sideEffects":false,"gitHead":"ae97adad847035e7839c7692aca4a44bd0540ee5","_id":"@chuli-dev/value-objects@0.5.0","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-j83TLibDccfejIV2XfLRpIo6wOgFlaYAf7BLJlTen062AiglcSU8p7fMgvW6DvBRL3Oge2fELZhrpadfDQNMeg==","shasum":"49c08967c0cf024d1501545a308c1aabbe82ba9a","tarball":"https://registry.npmjs.org/@chuli-dev/value-objects/-/value-objects-0.5.0.tgz","fileCount":81,"unpackedSize":62435,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHtBYnglzxCbf23XiPO6uP7+V0pyy50ltOIH+47R6NsDAiBZ7aCpBF58RtHxxZ3XI55VppdZTte9BSNUp+6U6hIvxg=="}]},"_npmUser":{"name":"chuli-dev","email":"tomasantunez.dev@gmail.com"},"directories":{},"maintainers":[{"name":"chuli-dev","email":"tomasantunez.dev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/value-objects_0.5.0_1783813320781_0.17515683635672752"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-09T01:54:00.438Z","modified":"2026-07-11T23:42:01.068Z","0.1.0":"2026-05-09T01:54:00.674Z","0.2.0":"2026-05-09T18:21:37.955Z","0.3.0":"2026-05-09T22:43:11.887Z","0.4.0":"2026-05-16T21:49:49.959Z","0.5.0":"2026-07-11T23:42:00.947Z"},"bugs":{"url":"https://github.com/TomasAntunez/chuli-dev-libs/issues"},"author":{"name":"chuli-dev"},"license":"MIT","homepage":"https://github.com/TomasAntunez/chuli-dev-libs/tree/main/libs/value-objects","keywords":["value-objects","ddd","domain","typescript"],"repository":{"type":"git","url":"git+https://github.com/TomasAntunez/chuli-dev-libs.git","directory":"libs/value-objects"},"description":"Value object base class and primitives for DDD","maintainers":[{"name":"chuli-dev","email":"tomasantunez.dev@gmail.com"}],"readme":"# @chuli-dev/value-objects\n\nValue Object base classes and primitives for DDD-style TypeScript applications.\n\n## ✨ Features\n\n- **DDD-friendly** - Immutable, self-validating Value Objects with structural equality\n- **Strict encapsulation** - `protected` constructors and `static` factory methods only\n- **Reusable validation** - Static `validate` / `validateString` methods you can call without instantiating\n- **Customizable error messages** - Override the default message per call, with structured metadata in every error\n- **Dual ESM/CJS** - Ships both module formats with proper conditional exports and TypeScript declarations\n- **Cross-platform** - Works in Node.js, modern browsers, Bun and Deno (no external runtime dependencies)\n\n## 📦 Installation\n\n```bash\nnpm install @chuli-dev/value-objects @chuli-dev/errors\n```\n\n`@chuli-dev/errors` is declared as a peer dependency so consumers share a single instance across all `@chuli-dev/*` libraries that rely on it.\n\n## 🚀 Quick Start\n\n```ts\nimport { Decimal, Uuid } from '@chuli-dev/value-objects';\n\nconst id = Uuid.create();\nconst price = Decimal.fromNumber(19.99);\n\nconsole.log(id.toString()); // e.g. '7c9e6679-7425-40de-944b-e07fc1f90ae7'\nconsole.log(price.toNumber()); // 19.99\n```\n\nParsing untrusted input (throws `InvalidValueError` on failure):\n\n```ts\nimport { Integer } from '@chuli-dev/value-objects';\n\nconst age = Integer.fromString(req.body.age, {\n  message: 'Age must be an integer',\n});\n```\n\nCatching validation errors:\n\n```ts\nimport { Integer, InvalidValueError } from '@chuli-dev/value-objects';\n\ntry {\n  Integer.fromString('not-a-number');\n} catch (err) {\n  if (err instanceof InvalidValueError) {\n    console.error(err.message, err.metadata); // { value: 'not-a-number' }\n  }\n}\n```\n\n## 📋 Available Value Objects\n\n### Foundation\n\n| Class             | Description                                                         |\n| ----------------- | ------------------------------------------------------------------- |\n| **`ValueObject`** | Abstract marker base class for all Value Objects                    |\n| **`Primitive`**   | Abstract base for single-value primitives (string, number, boolean) |\n\n### Primitives\n\n| Class         | Description                                                 |\n| ------------- | ----------------------------------------------------------- |\n| **`Text`**    | Non-empty string (trimmed)                                  |\n| **`Decimal`** | Finite number (rejects `NaN` / `Infinity`)                  |\n| **`Bool`**    | Boolean. Strict `'true'` / `'false'` parsing                |\n| **`Integer`** | Integer number                                              |\n| **`Uuid`**    | RFC 4122 UUID (versions 1-7). `create()` generates a new v4 |\n\n### Numeric refinements\n\n| Class                    | Constraint   |\n| ------------------------ | ------------ |\n| **`PositiveDecimal`**    | `value > 0`  |\n| **`NegativeDecimal`**    | `value < 0`  |\n| **`NonNegativeDecimal`** | `value >= 0` |\n| **`NonPositiveDecimal`** | `value <= 0` |\n| **`PositiveInteger`**    | `value > 0`  |\n| **`NegativeInteger`**    | `value < 0`  |\n| **`NonNegativeInteger`** | `value >= 0` |\n| **`NonPositiveInteger`** | `value <= 0` |\n\n## 🛠️ The Validation Contract\n\nEvery Value Object exposes a consistent set of static methods:\n\n```ts\nclass Some extends Primitive<T> {\n  // Validate a primitive value. Returns the normalized value when there's\n  // a transformation (e.g. trimming, lowercasing); otherwise returns void.\n  static validate(value: T, options?: ValidateOptions): T | void;\n\n  // Validate a string representation and return the parsed primitive.\n  // Available where parsing applies (Decimal, Bool, Integer, ...).\n  static validateString(value: string, options?: ValidateOptions): T;\n\n  // Factory methods. Validate first, then build the instance.\n  static fromX(value: T, options?: ValidateOptions): Some;\n  static fromString(value: string, options?: ValidateOptions): Some;\n}\n```\n\n`ValidateOptions` lets you override the default error message:\n\n```ts\ninterface ValidateOptions {\n  message?: string;\n}\n```\n\nEvery failure throws an `InvalidValueError` with the offending input attached as `metadata.value`.\n\n### Reusing validation without an instance\n\nThe `validate` / `validateString` methods are useful when you need to check input but don't want to allocate a Value Object:\n\n```ts\nimport { Integer } from '@chuli-dev/value-objects';\n\nif (req.query.page) {\n  Integer.validateString(req.query.page); // throws if invalid\n}\n```\n\n## 🟰 Equality\n\nValue Objects compare by **structural equality**, not by reference:\n\n```ts\nimport { Text } from '@chuli-dev/value-objects';\n\nconst a = Text.fromString('hello');\nconst b = Text.fromString('hello');\n\na === b; // false\na.isEqualTo(b); // true\n```\n\n`isEqualTo` checks the wrapped value only. Two `Primitive<T>` instances with matching values are equal even across the inheritance hierarchy — for example, a `Text` and a custom `Email extends Text` carrying the same string. TypeScript enforces type compatibility at compile time via the `other: this` parameter, so you can't accidentally compare across unrelated primitive types (e.g. `Text` with `Decimal`).\n\n## 🧱 Creating your own Value Objects\n\nExtend any of the provided classes to model domain-specific concepts:\n\n```ts\nimport { InvalidValueError, Text, type ValidateOptions } from '@chuli-dev/value-objects';\n\nconst EMAIL_REGEX = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\nexport class Email extends Text {\n  static override validate(value: string, options: ValidateOptions = {}): string {\n    const trimmed = super.validate(value, options);\n\n    if (!EMAIL_REGEX.test(trimmed)) {\n      throw new InvalidValueError(options.message ?? 'Value must be a valid email', {\n        metadata: { value },\n      });\n    }\n\n    return trimmed.toLowerCase();\n  }\n\n  static override fromString(value: string, options: ValidateOptions = {}): Email {\n    return new Email(Email.validate(value, options));\n  }\n}\n```\n\nA few rules to keep the contract consistent:\n\n- Keep constructors `protected` and expose only `static` factories.\n- Override `validate` (and `validateString` where applicable) to compose with `super`.\n- Override the matching `fromX` factories so they return your subclass type.\n\n## 📝 Notes\n\n- Value Objects are immutable by convention (`readonly` fields). They are not frozen at runtime to keep allocation cheap.\n- `Uuid.create()` relies on the global `crypto.randomUUID()`. It works in Node.js `>=19`, modern browsers (secure contexts only), Bun and Deno.\n- `InvalidValueError` extends `ValidationError` from [`@chuli-dev/errors`](https://www.npmjs.com/package/@chuli-dev/errors), so you can catch any validation failure from this library — including your own subclasses — by `instanceof InvalidValueError`.\n\n## 🔧 Requirements\n\n- **TypeScript** `>=5` (only if consuming the type declarations)\n\n## 📄 License\n\nMIT - see the [LICENSE](https://github.com/TomasAntunez/chuli-dev-libs/blob/main/libs/value-objects/LICENSE) file for details.\n\n## 👤 Author\n\n**chuli-dev** - [@TomasAntunez](https://github.com/TomasAntunez)\n","readmeFilename":"README.md"}