{"_id":"@azghr/specie","_rev":"3-ece38d878405cd882e082664065e5b14","name":"@azghr/specie","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@azghr/specie","version":"0.1.0","keywords":["money","currency","arithmetic","formatting","intl","cents","financial","decimal","rounding","allocation"],"license":"MIT","_id":"@azghr/specie@0.1.0","maintainers":[{"name":"azghr","email":"masgharali.eng@gmail.com"}],"dist":{"shasum":"8abb1d4b48e8324b7a8b81758500e417156b25e7","tarball":"https://registry.npmjs.org/@azghr/specie/-/specie-0.1.0.tgz","fileCount":10,"integrity":"sha512-rTsbbNueJthackeh1NXOIwULk7vTRy0xfO1p2BkhgY+cH3Dj9YRvjwX+blh63kMQhQKNYuG6dJl+DzGkOM/9Og==","signatures":[{"sig":"MEUCIQDIwleCnxIQzkltlj4DCi+CArnDomxNUwNJB/x4C9PV5QIgNePOmCVAuGrIQgEQ/7Tz0N2N3P2x2hvhT81yiubVMFE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":62947},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"3236cd058fa28bde79ff26fdc6b5fd8d4efdd65e","scripts":{"demo":"tsx examples/demo.ts","lint":"eslint src test examples","test":"vitest run","build":"tsup src/index.ts --format esm,cjs --dts --sourcemap --clean","check":"npm run typecheck && npm run lint && npm run test && npm run build","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run check"},"_npmUser":{"name":"azghr","email":"masgharali.eng@gmail.com"},"_npmVersion":"11.6.2","description":"Tiny integer-cents money type — safe arithmetic, currency-aware rounding, Intl formatting. No bignum, no dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","tsup":"^8.3.5","eslint":"^9.18.0","vitest":"^2.1.8","@eslint/js":"^9.18.0","typescript":"^5.7.3","typescript-eslint":"^8.19.1"},"_npmOperationalInternal":{"tmp":"tmp/specie_0.1.0_1784663501385_0.6473978219140522","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@azghr/specie","version":"0.1.1","keywords":["money","currency","arithmetic","formatting","intl","cents","financial","decimal","rounding","allocation"],"license":"MIT","_id":"@azghr/specie@0.1.1","maintainers":[{"name":"azghr","email":"masgharali.eng@gmail.com"}],"dist":{"shasum":"5cefabf09ab7ada76529ea815d7249425e909bad","tarball":"https://registry.npmjs.org/@azghr/specie/-/specie-0.1.1.tgz","fileCount":10,"integrity":"sha512-p061hdXcHQVqnjsMWh87vOJsQKxTGd6YQLcwpTBXhef8gbTMGg/WbKXu7mO4tNV6PNNhObwPhmuvmZyks7+ryg==","signatures":[{"sig":"MEQCIBQkj3wvQeDPomqiuBC7XzICO9AGeTLzi9JbWeM/875KAiBPnuDJuNeVVUdQNwcRvkM9ZsMc/76r0RfLbwSdGv2kmA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":63330},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"673c464256ed29f1f290d9f3b4f94cfe42e6a14d","scripts":{"demo":"tsx examples/demo.ts","lint":"eslint src test examples","test":"vitest run","build":"tsup src/index.ts --format esm,cjs --dts --sourcemap --clean","check":"npm run typecheck && npm run lint && npm run test && npm run build","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run check"},"_npmUser":{"name":"azghr","email":"masgharali.eng@gmail.com"},"_npmVersion":"11.6.2","description":"Tiny integer-cents money type — safe arithmetic, currency-aware rounding, Intl formatting. No bignum, no dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","tsup":"^8.3.5","eslint":"^9.18.0","vitest":"^2.1.8","@eslint/js":"^9.18.0","typescript":"^5.7.3","typescript-eslint":"^8.19.1"},"_npmOperationalInternal":{"tmp":"tmp/specie_0.1.1_1784722989485_0.9113809460180602","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@azghr/specie","version":"0.1.2","description":"Tiny integer-cents money type — safe arithmetic, currency-aware rounding, Intl formatting. No bignum, no dependencies.","license":"MIT","type":"module","sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"engines":{"node":">=18"},"scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --sourcemap --clean","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","lint":"eslint src test examples","demo":"tsx examples/demo.ts","check":"npm run typecheck && npm run lint && npm run test && npm run build","prepublishOnly":"npm run check"},"keywords":["money","currency","arithmetic","formatting","intl","cents","financial","decimal","rounding","allocation"],"devDependencies":{"@eslint/js":"^9.18.0","eslint":"^9.18.0","tsx":"^4.19.2","typescript":"^5.7.3","typescript-eslint":"^8.19.1","vitest":"^2.1.8","tsup":"^8.3.5"},"gitHead":"7d3bdd3d558c981596249dadffb12e4703098764","_id":"@azghr/specie@0.1.2","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-bKWSL+bHrkj1GkH5oYzeUDgADoGBGuggvsQYkD4BJl55luKVmNepELrIrvm/sRPGQDNgMre9H65RZXE614mkLw==","shasum":"e400afc37632008a268fbbee293cb0caf5e0768e","tarball":"https://registry.npmjs.org/@azghr/specie/-/specie-0.1.2.tgz","fileCount":10,"unpackedSize":65081,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHPKxR4WKNbsiFRj6njom1V+ATB6HtWgMbGPMQrrv5hxAiEA+mjFy2n8AmCb6TYbxJKjsNBwOySB7TxLxLCjAToSZ9M="}]},"_npmUser":{"name":"azghr","email":"masgharali.eng@gmail.com"},"directories":{},"maintainers":[{"name":"azghr","email":"masgharali.eng@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/specie_0.1.2_1784746494445_0.762470232171464"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-21T19:51:41.243Z","modified":"2026-07-22T18:54:54.750Z","0.1.0":"2026-07-21T19:51:41.510Z","0.1.1":"2026-07-22T12:23:09.651Z","0.1.2":"2026-07-22T18:54:54.594Z"},"license":"MIT","keywords":["money","currency","arithmetic","formatting","intl","cents","financial","decimal","rounding","allocation"],"description":"Tiny integer-cents money type — safe arithmetic, currency-aware rounding, Intl formatting. No bignum, no dependencies.","maintainers":[{"name":"azghr","email":"masgharali.eng@gmail.com"}],"readme":"# specie\n\n[![npm](https://img.shields.io/npm/v/@azghr/specie)](https://www.npmjs.com/package/@azghr/specie)\n[![MIT License](https://img.shields.io/npm/l/@azghr/specie)](LICENSE)\n\nTiny integer-cents money type — safe arithmetic, currency-aware rounding, Intl formatting. No bignum, no dependencies.\n\n## The Problem\n\n`0.1 + 0.2 !== 0.3`. Storing money as floats produces rounding errors and audit nightmares. Correct money is integer minor units + a currency + explicit rounding + locale formatting.\n\nThis is competitive space: dinero.js, big.js, and decimal.js cover arbitrary decimals. specie is worth building only because it stays radically smaller: integer minor units only, currency-aware default fractions via Intl, and a few explicit operations.\n\n## Install\n\n```bash\nnpm install @azghr/specie\n# or\npnpm add @azghr/specie\n# or\nyarn add @azghr/specie\n```\n\n## Use\n\n```typescript\nimport { money, fromDecimal } from \"@azghr/specie\";\n\n// 10-second copy-paste\nconst price = money(1999, \"USD\");           // $19.99 as 1999 cents\nprice.add(money(100, \"USD\")).format();    // \"$20.99\"\n\n// Realistic usage\nconst subtotal = fromDecimal(\"19.99\", \"USD\");\nconst tax = subtotal.multiply(0.0825);     // 8.25% tax\nconst total = subtotal.add(tax);\ntotal.format();                          // \"$21.64\"\n```\n\n## API\n\n### `money(amount: number, currency: string): Money`\nCreate Money from integer minor units. `amount` must be a safe integer.\n\n```typescript\nmoney(1999, \"USD\")  // $19.99\nmoney(500, \"JPY\")   // ¥500\n```\n\n### `fromDecimal(value: string, currency: string): Money`\nParse decimal string to Money. Never uses float parsing to avoid rounding errors.\n\n```typescript\nfromDecimal(\"19.99\", \"USD\")  // 1999 cents\nfromDecimal(\"-10.50\", \"USD\") // -1050 cents\n```\n\n### `Money.add(other: Money): Money`\nAdd another Money value (same currency only). Throws `CurrencyMismatch` on currency mismatch.\n\n### `Money.subtract(other: Money): Money`\nSubtract another Money value (same currency only).\n\n### `Money.multiply(factor: number, rounding?: Rounding): Money`\nMultiply by a factor with rounding. Default: `\"half-even\"` (banker's rounding).\n\n```typescript\nmoney(1000, \"USD\").multiply(1.0825)              // Apply 8.25% tax\nmoney(100, \"USD\").multiply(1.5, \"half-up\")       // Force ties up\n```\n\n### `Money.allocate(ratios: readonly number[]): Money[]`\nDistribute by ratios using largest-remainder method. Parts sum exactly to the original amount.\n\n```typescript\nmoney(100, \"USD\").allocate([3, 2])  // [$60, $40] (not $59.99/$40.01)\n```\n\n### `Money.format(locale?: string): string`\nFormat using `Intl.NumberFormat`.\n\n```typescript\nmoney(1999, \"USD\").format()        // \"$19.99\"\nmoney(123456, \"JPY\").format(\"ja-JP\") // \"￥123,456\" (no decimals)\n```\n\n### `Money.compare(other: Money): -1 | 0 | 1`\nCompare with another Money. Throws `CurrencyMismatch` on currency mismatch.\n\n### `Money.equals(other: Money): boolean`\nCheck equality.\n\n### `Money.isZero()`, `Money.isNegative()`, `Money.isPositive()`\nCheck amount sign.\n\n### `Money.toJSON(): { amount: number; currency: string }`\nSerialize to plain object.\n\n### Type: `Rounding`\n\n```typescript\n\"half-up\" | \"half-even\" | \"down\" | \"up\"\n```\n\n### Class: `CurrencyMismatch`\n\nError thrown when operations mix different currencies.\n\n## Non-Goals\n\nUse dinero.js or decimal.js for:\n- Arbitrary precision / values beyond `Number.MAX_SAFE_INTEGER`\n- Multi-currency conversion / forex\n- Historical rates\n- Crypto amounts with 18 decimals\n\n## TypeScript Note\n\n```typescript\nimport { money, fromDecimal } from \"@azghr/specie\";\n\n// Full type safety\nconst price: Money = money(1999, \"USD\");\nconst total: Money = price.add(money(500, \"USD\"));\n\n// Currency mismatch caught at compile time\nconst usd = money(100, \"USD\");\nconst eur = money(100, \"EUR\");\n// usd.add(eur) // TypeScript: this works, runtime throws CurrencyMismatch\n```\n\n## Related Packages\n\n**Caching & Concurrency:**\n- **[@azghr/filterkit](https://www.npmjs.com/package/@azghr/filterkit)** — Framework-agnostic, type-safe filtering for TypeScript\n- **[@azghr/singlet](https://www.npmjs.com/package/@azghr/singlet)** — Deduplicate concurrent async calls\n- **[staleness](https://www.npmjs.com/package/staleness)** — Stale-while-revalidate caching for async functions\n\n**Text Processing:**\n- **[@azghr/shorn](https://www.npmjs.com/package/@azghr/shorn)** — Truncate strings by byte budget without breaking graphemes\n- **[seriatim](https://www.npmjs.com/package/seriatim)** — Sequential processing utilities\n\n**HTTP & Network:**\n- **[forbear](https://www.npmjs.com/package/forbear)** — Read server rate-limit instructions from HTTP responses\n- **[forestall](https://www.npmjs.com/package/forestall)** — Delay execution until a condition is met\n- **[obviate](https://www.npmjs.com/package/obviate)** — Render operations unnecessary through caching\n\n**System & Process:**\n- **[quiesce](https://www.npmjs.com/package/quiesce)** — Ordered, timeboxed graceful shutdown for Node\n- **[sortition](https://www.npmjs.com/package/sortition)** — Deterministic percentage rollouts and A/B bucketing\n- **[stanch](https://www.npmjs.com/package/stanch)** — Stop flows or operations based on conditions\n\n**Utilities:**\n- **[expunge](https://www.npmjs.com/package/expunge)** — Remove or exclude items from collections\n- **[occlude](https://www.npmjs.com/package/occlude)** — Hide or mask data and functionality\n- **[placemark](https://www.npmjs.com/package/placemark)** — Geographic location and mapping utilities\n\n## License\n\nMIT\n","readmeFilename":"README.md"}