@cellarnode/finance

中文文档
0.5.0发布于 2026/10/20UNLICENSEDTypeScriptES Module近 30 天下载 3353

Canonical price-range Zod schemas, BASIS enum, money helpers for CellarNode (headless TypeScript).

原始使用文档
文档目录11 节
  1. Install
  2. Exports
  3. Quick examples
  4. Validate a price range
  5. Inherit defaults from a portfolio profile
  6. Format a price range for display
  7. Compare a normalized price amount
  8. Why this package?
  9. Development
  10. Publishing
  11. License

@cellarnode/finance

Canonical price-range Zod schemas, BASIS enum, currency helpers, format helpers, and inheritance helpers for CellarNode. Headless TypeScript — no React, no UI deps.

Install

pnpm add @cellarnode/finance zod
# or
npm install @cellarnode/finance zod
# or
bun add @cellarnode/finance zod

zod is a peer dependency.

Exports

import {
  // BASIS
  BASIS, type Basis,

  // Price ranges
  priceRangeSchema, type PriceRange,
  fingerprintRange,

  // Chosen price ranges (with rangeRef + label)
  chosenPriceRangeSchema, type ChosenPriceRange,

  // Inheritance
  resolveEffective,
  type DefaultPriceProfile,
  type EffectiveRange,

  // Currency
  isValidCurrencyCode,
  getCurrencyName,
  getMinorUnits,

  // Formatting
  formatMoney,
  formatBasis,
  formatPriceRange,
} from "@cellarnode/finance";

Quick examples

Validate a price range

import { priceRangeSchema } from "@cellarnode/finance";

const range = priceRangeSchema.parse({
  min: 12.0,
  max: 18.0,
  currency: "EUR",
  basis: "per_unit",
  priceTypeId: "fob",
  priceTypeOther: null,
  basisNote: null,
});

Validation rules (superRefine):

  • max >= min
  • priceTypeId and priceTypeOther are mutually exclusive
  • basisNote is required iff basis === "other"

Inherit defaults from a portfolio profile

import { resolveEffective } from "@cellarnode/finance";

const range = { min: 1, max: 2, currency: null, basis: null, priceTypeId: null, priceTypeOther: null, basisNote: null };
const profile = { currency: "EUR", basis: "per_unit", priceTypeId: "fob" };
const effective = resolveEffective(range, profile);
// → { min:1, max:2, currency:"EUR", basis:"per_unit", priceTypeId:"fob", ... }

Format a price range for display

import { formatPriceRange } from "@cellarnode/finance";

formatPriceRange({ min: 12, max: 18, currency: "EUR", basis: "per_unit", ... });
// → "€12.00 - €18.00 per unit"

Compare a normalized price amount

import { compareNormalizedPriceAmount } from "@cellarnode/finance";

const result = compareNormalizedPriceAmount({
  amount: 7.5,
  min: null,
  max: 10,
  fromBasis: "per_unit",
  toBasis: "per_litre",
  packageVolumeMl: 750,
  fxRate: 1,
});
// { ok: true, relation: "within", comparisonAmount: 10 }

Bounds are inclusive, finite, nonnegative and ordered; null opens one side. Both bounds cannot be null. Amount must be finite and nonnegative, and FX rate must be positive and finite (pass 1 for the same currency). A supplied package volume must be positive and finite, and is required when the bases differ. Only canonical per_unit and per_litre bases are accepted by the input type.

Each operand means its String(number) decimal spelling, including exponents. The relation uses exact rational arithmetic without currency rounding or tolerance. The informational comparisonAmount is rounded to a JavaScript number only after comparison; it may equal a bound even when the exact relation is outside it. Overflow or a positive result rounding to zero returns { ok: false, reason: "unrepresentable_amount" }. Other failure reasons are invalid_amount, invalid_bounds, invalid_fx_rate, and invalid_package_volume. No BigInt values leave the helper.

The caller owns currency identity, FX selection/freshness, trusted package volume, qualified case identity, and unconstrained-range handling. This helper performs no I/O, mutation, scoring or policy evaluation.

Why this package?

Before @cellarnode/finance, the canonical price-range Zod schema lived in cellarnode-backend-v2/src/features/opportunities/price-range-schema.ts. Three dashboards (admin, producer, importer) duplicated the validation rules — one drift was already observed during Spec 1 implementation. This package owns the wire format end-to-end so all consumers stay in sync.

Development

make build       # clean + typecheck + compile
make test        # vitest run
make test-watch  # vitest watch
make typecheck   # tsc --noEmit
make check-exports  # publint + arethetypeswrong

Publishing

Published to npm (public access — publishConfig.access: "public", see CEL-1983) via npm Trusted Publishing (OIDC) — .github/workflows/publish.yml publishes automatically on a merge to main that changes package.json's version. There is no long-lived npm token in the publish job, and nobody runs npm publish by hand. This is a private repo, so unlike @cellarnode/beverage-utils, npm does not generate provenance attestations for this package.

Cut a release locally, then land it through a normal PR:

make release-patch   # bump patch, commit, tag
make release-minor   # bump minor, commit, tag
make release-major   # bump major, commit, tag

These targets bump package.json, build, commit, and tag — they do not publish. Push the branch, open a PR, and merging to main triggers CI's publish job.

License

UNLICENSED — Copyright (c) CellarNode. All rights reserved. This package is published for CellarNode's own applications; no license is granted for other use.

版本与发布记录

@cellarnode/finance 共发布 9 个版本,首次发布于 2026/04/24;过去 12 个月发布了 9 个版本。

版本发布日期距今
0.5.0latest2026/10/2020 天前
0.4.32026/09/151 个月前
0.4.22026/08/132 个月前
0.4.12026/06/174 个月前
0.4.02026/06/104 个月前
0.3.02026/05/275 个月前

关于 @cellarnode/finance 的常见问题

@cellarnode/finance 是什么?

Canonical price-range Zod schemas, BASIS enum, money helpers for CellarNode (headless TypeScript).

如何安装 @cellarnode/finance?

在项目目录运行 npm install @cellarnode/finance,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:zod(^3.25.0 || ^4.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@cellarnode/finance 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@cellarnode/finance 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@cellarnode/finance 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.19.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@cellarnode/finance 可以商用吗?

@cellarnode/finance 使用 UNLICENSED 许可。作者声明为 UNLICENSED,即不授予公开使用许可(与公共领域的 Unlicense 不同)。使用前需获得作者授权。以上为概括,不构成法律意见,请以许可原文为准。

@cellarnode/finance 的下载量有多少?

根据 npm 官方下载统计,@cellarnode/finance 在 2026/10/10 – 2026/11/08 这 30 天内被下载 3,353 次,日均约 112 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cellarnode/finance 还在维护吗?

最新版本 0.5.0 发布于 2026/10/20(20 天前);至今共发布 9 个版本,其中过去 12 个月发布了 9 个;首次发布于 2026/04/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。