@amboras-dev/money 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +393 -2
  2. package/dist/ai.cjs +185 -0
  3. package/dist/ai.d.cts +97 -0
  4. package/dist/ai.d.ts +97 -0
  5. package/dist/ai.js +175 -0
  6. package/dist/allocate-CdnhvAda.js +199 -0
  7. package/dist/allocate-D7tm_t_o.cjs +222 -0
  8. package/dist/amount-D7dj76nH.js +200 -0
  9. package/dist/amount-DHtvZSSm.cjs +241 -0
  10. package/dist/arithmetic-Bq-8mSal.cjs +233 -0
  11. package/dist/arithmetic-C-Q_aI49.js +132 -0
  12. package/dist/billing.cjs +184 -0
  13. package/dist/billing.d.cts +81 -0
  14. package/dist/billing.d.ts +81 -0
  15. package/dist/billing.js +175 -0
  16. package/dist/commerce.cjs +536 -0
  17. package/dist/commerce.d.cts +293 -0
  18. package/dist/commerce.d.ts +293 -0
  19. package/dist/commerce.js +516 -0
  20. package/dist/format-BdB7LEIp.js +90 -0
  21. package/dist/format-BnA1aLJk.cjs +113 -0
  22. package/dist/fx.cjs +407 -0
  23. package/dist/fx.d.cts +157 -0
  24. package/dist/fx.d.ts +157 -0
  25. package/dist/fx.js +374 -0
  26. package/dist/index.cjs +349 -0
  27. package/dist/index.d.cts +288 -0
  28. package/dist/index.d.ts +288 -0
  29. package/dist/index.js +276 -0
  30. package/dist/input.cjs +163 -0
  31. package/dist/input.d.cts +203 -0
  32. package/dist/input.d.ts +203 -0
  33. package/dist/input.js +153 -0
  34. package/dist/iso-minor--gQWI1f2.cjs +65 -0
  35. package/dist/iso-minor-CtaiIifs.js +48 -0
  36. package/dist/medusa-CmxCni-G.js +101 -0
  37. package/dist/medusa-DuQ3-KoD.d.cts +78 -0
  38. package/dist/medusa-OJ2TJOxt.cjs +154 -0
  39. package/dist/medusa-RwqxaDGq.d.ts +78 -0
  40. package/dist/money-CIgELekG.js +3571 -0
  41. package/dist/money-CbhsT0fB.d.cts +232 -0
  42. package/dist/money-CbhsT0fB.d.ts +232 -0
  43. package/dist/money-D5-vlv0h.cjs +3960 -0
  44. package/dist/number-text-BpvN6NAo.cjs +145 -0
  45. package/dist/number-text-C82oh6JB.js +134 -0
  46. package/dist/own-D7544D3k.js +4 -0
  47. package/dist/own-oP9DXFWv.cjs +9 -0
  48. package/dist/percent-CKVI_c-m.js +20 -0
  49. package/dist/percent-Dt8vNIAW.cjs +43 -0
  50. package/dist/rate-CmeTGNex.d.ts +63 -0
  51. package/dist/rate-DGPfB_jc.cjs +217 -0
  52. package/dist/rate-lLPViBuM.js +152 -0
  53. package/dist/rate-toyS3EMf.d.cts +63 -0
  54. package/dist/reporting-5xby-Zas.d.ts +31 -0
  55. package/dist/reporting-DEM97DhQ.d.cts +31 -0
  56. package/dist/retail-BsvpNv1F.js +69 -0
  57. package/dist/retail-BwcFJcVN.d.ts +31 -0
  58. package/dist/retail-DTk2XAMM.cjs +86 -0
  59. package/dist/retail-Mqd-sPMF.d.cts +31 -0
  60. package/dist/rounding-CVAPEfq_.js +50 -0
  61. package/dist/rounding-oZ832yTD.cjs +79 -0
  62. package/dist/sql.cjs +290 -0
  63. package/dist/sql.d.cts +147 -0
  64. package/dist/sql.d.ts +147 -0
  65. package/dist/sql.js +271 -0
  66. package/dist/testing.cjs +28518 -0
  67. package/dist/testing.d.cts +97 -0
  68. package/dist/testing.d.ts +97 -0
  69. package/dist/testing.js +28510 -0
  70. package/dist/wire-CI3Sm1iC.js +1675 -0
  71. package/dist/wire-Cd4Q1Jmm.d.ts +269 -0
  72. package/dist/wire-DQZ6fA3c.cjs +1872 -0
  73. package/dist/wire-hWuixv3w.d.cts +269 -0
  74. package/dist/wire.cjs +35 -0
  75. package/dist/wire.d.cts +2 -0
  76. package/dist/wire.d.ts +2 -0
  77. package/dist/wire.js +2 -0
  78. package/package.json +158 -3
package/dist/input.js ADDED
@@ -0,0 +1,153 @@
1
+ import { Z as MoneyError, dt as toDecimalText, et as compareDecimal, it as fractionDigitsOf, lt as roundToScale, rt as formatDecimal, s as storedDecimal, z as decimalOf } from "./money-CIgELekG.js";
2
+ import { n as readNumberText } from "./number-text-C82oh6JB.js";
3
+ import { c as rateFromDecimal, o as rate } from "./rate-lLPViBuM.js";
4
+ import { a as inputStep, i as inputPlaceholder, n as formatAmountInput, o as localeSeparators, r as groupDigits, s as parseAmountInput, t as decimalOfText } from "./amount-D7dj76nH.js";
5
+ //#region src/input/import.ts
6
+ /**
7
+ * Amount text from a file or a third party to canonical DecimalText (major units, exactly as
8
+ * written: `'1.299,00'` gives `'1299'`), or null when it is not an amount (empty, exponent,
9
+ * hex, garbage, negative without `allowNegative`). Never 0 for bad input.
10
+ */
11
+ function parseImportAmount(text, options = {}) {
12
+ const read = readNumberText(text, {
13
+ decimalSeparator: options.decimalSeparator ?? "auto",
14
+ currency: options.currency,
15
+ allowTrailingText: options.allowTrailingText
16
+ });
17
+ if ("reason" in read || read.sign < 0 && !options.allowNegative) return null;
18
+ return toDecimalText(decimalOfText(read));
19
+ }
20
+ /**
21
+ * Strict decimal entry: `.` decimal, no grouping, at most `maxDecimals` fraction digits (cost
22
+ * entry at 4, metafields). `'4.5'` gives `'4.5'`, `'.5'` gives `'0.5'`; `'1,000'` is `'unparseable'`.
23
+ */
24
+ function parseDecimalInput(text, options) {
25
+ const read = readNumberText(text, {
26
+ decimalSeparator: ".",
27
+ groupSeparator: null
28
+ });
29
+ if ("reason" in read) return {
30
+ ok: false,
31
+ reason: read.reason
32
+ };
33
+ const value = decimalOfText(read);
34
+ if (fractionDigitsOf(value) > options.maxDecimals) return {
35
+ ok: false,
36
+ reason: "too_many_decimals"
37
+ };
38
+ if (value.units < 0n && !options.allowNegative) return {
39
+ ok: false,
40
+ reason: "negative"
41
+ };
42
+ if (options.min !== void 0 && compareDecimal(value, decimalOf(options.min)) < 0) return {
43
+ ok: false,
44
+ reason: "below_min"
45
+ };
46
+ if (options.max !== void 0 && compareDecimal(value, decimalOf(options.max)) > 0) return {
47
+ ok: false,
48
+ reason: "above_max"
49
+ };
50
+ return {
51
+ ok: true,
52
+ value: toDecimalText(value)
53
+ };
54
+ }
55
+ //#endregion
56
+ //#region src/input/percent-rate.ts
57
+ /**
58
+ * A typed percent (`'20'`, `'12.5'`, `'12,5 %'` in de-DE) as DecimalText. A `%` before or after
59
+ * the number is allowed. Default range 0..100 with 2 decimals; below 0 (with a non-negative
60
+ * `min`) is `'negative'`.
61
+ */
62
+ function parsePercentInput(text, options = {}) {
63
+ const bare = typeof text === "string" ? text.trim().replace(/^%\s*|\s*%$/g, "") : text;
64
+ const read = readNumberText(bare, localeSeparators(options.locale));
65
+ if ("reason" in read) return {
66
+ ok: false,
67
+ reason: read.reason
68
+ };
69
+ const value = decimalOfText(read);
70
+ const min = decimalOf(options.min ?? 0, true, "min");
71
+ const max = decimalOf(options.max ?? 100, true, "max");
72
+ if (fractionDigitsOf(value) > (options.maxDecimals ?? 2)) return {
73
+ ok: false,
74
+ reason: "too_many_decimals"
75
+ };
76
+ if (compareDecimal(value, min) < 0) return {
77
+ ok: false,
78
+ reason: value.units < 0n && min.units >= 0n ? "negative" : "below_min"
79
+ };
80
+ if (compareDecimal(value, max) > 0) return {
81
+ ok: false,
82
+ reason: "above_max"
83
+ };
84
+ return {
85
+ ok: true,
86
+ value: toDecimalText(value)
87
+ };
88
+ }
89
+ /**
90
+ * A typed exchange rate ("1 store-currency unit equals this many units") as a precise Rate
91
+ * (`fx.rateFromDecimal(value, { encoding: 'precise' })`), or null when the text is not a
92
+ * positive number or the rate is outside `RATE_BOUNDS` (0.0000001 to 1000000000).
93
+ */
94
+ function parseRateInput(text, options = {}) {
95
+ const read = readNumberText(text, localeSeparators(options.locale));
96
+ if ("reason" in read || read.sign < 0 || read.units === 0n) return null;
97
+ try {
98
+ const precise = rateFromDecimal(formatDecimal(decimalOfText(read)), { encoding: "precise" });
99
+ return rate(precise.numerator, precise.denominator);
100
+ } catch (error) {
101
+ if (error instanceof MoneyError && error.code === "rate_invalid") return null;
102
+ throw error;
103
+ }
104
+ }
105
+ //#endregion
106
+ //#region src/input/template.ts
107
+ const DEFAULT_TEMPLATE = Object.freeze({
108
+ prefix: "",
109
+ suffix: "",
110
+ fractionDigits: 2,
111
+ decimalSeparator: ".",
112
+ groupSeparator: ","
113
+ });
114
+ const NUMBER_RUN = /\d[\d.,'’\s]*\d|\d/u;
115
+ const counterpart = (separator) => separator === "," ? "." : ",";
116
+ /**
117
+ * The print template of one captured literal (cloner `analyzeMoneyFormat`): prefix and suffix
118
+ * around the number, the decimal separator and digit count of its fraction (1 or 2 digits
119
+ * read as 2, 3 as 3, none as 0), the separator it groups thousands with (else the decimal's
120
+ * counterpart), all as the separator engine's `'auto'` rule reads them. A
121
+ * sample with no number gives `{ prefix: '', suffix: '', fractionDigits: 2, '.', ',' }`.
122
+ */
123
+ function moneyTemplateOf(sample) {
124
+ const text = typeof sample === "string" ? sample : "";
125
+ const run = NUMBER_RUN.exec(text);
126
+ if (!run) return DEFAULT_TEMPLATE;
127
+ const read = readNumberText(run[0], { decimalSeparator: "auto" });
128
+ if ("reason" in read) return DEFAULT_TEMPLATE;
129
+ const decimalSeparator = read.decimalMark ?? counterpart(read.groupMark ?? ",");
130
+ return Object.freeze({
131
+ prefix: text.slice(0, run.index),
132
+ suffix: text.slice(run.index + run[0].length),
133
+ fractionDigits: read.scale === 0 ? 0 : read.scale === 3 ? 3 : 2,
134
+ decimalSeparator,
135
+ groupSeparator: read.groupMark ?? counterpart(decimalSeparator)
136
+ });
137
+ }
138
+ /**
139
+ * Money printed with a captured template: the exact major amount (stored / storageScale)
140
+ * rounded half-up to the template's digits, grouped, the sign after the prefix
141
+ * (`moneyTemplateOf('Rp 199.000')` prints IDR 2500050 as `'Rp 25.001'`).
142
+ */
143
+ function formatWithTemplate(m, template) {
144
+ const { value } = storedDecimal(m);
145
+ const rounded = formatDecimal(roundToScale(value, template.fractionDigits, "half-up"));
146
+ const negative = rounded.startsWith("-");
147
+ const [whole, fraction] = (negative ? rounded.slice(1) : rounded).split(".");
148
+ const grouped = groupDigits(whole, template.groupSeparator);
149
+ const tail = fraction === void 0 ? "" : `${template.decimalSeparator}${fraction}`;
150
+ return `${template.prefix}${negative ? "-" : ""}${grouped}${tail}${template.suffix}`;
151
+ }
152
+ //#endregion
153
+ export { formatAmountInput, formatWithTemplate, inputPlaceholder, inputStep, moneyTemplateOf, parseAmountInput, parseDecimalInput, parseImportAmount, parsePercentInput, parseRateInput };
@@ -0,0 +1,65 @@
1
+ const require_money = require("./money-D5-vlv0h.cjs");
2
+ //#region src/iso-minor.ts
3
+ /**
4
+ * Internal: stored units per ISO minor unit at `digits`, `storageScale / 10^digits` (100 for
5
+ * a zero-digit count on a x100 currency, 1 when the digits match the storage exponent).
6
+ * `digits` above the storage exponent has no whole factor and throws `precision`.
7
+ */
8
+ function isoMinorFactor(info, digits) {
9
+ if (digits > require_money.storageExponent(info)) throw new require_money.MoneyError("precision", `${info.code} stores ${require_money.storageExponent(info)} implied decimals, fewer than ${digits}`);
10
+ return BigInt(info.storageScale) / require_money.pow10(digits);
11
+ }
12
+ /**
13
+ * ISO minor units at the display digits: `round(major x 10^displayDigits)` with `rounding`
14
+ * (default half-up). JPY 150000 gives 1500, KWD 1005 gives 1005, IQD 10000 gives 10, HUF
15
+ * 435050 gives 4351. Not for payment providers (use `/wire`).
16
+ */
17
+ function toIsoMinor(m, options = {}) {
18
+ const { info } = require_money.storedDecimal(m);
19
+ return Number(require_money.mulDiv(BigInt(m.amount), 1n, isoMinorFactor(info, info.displayDigits), options.rounding ?? "half-up"));
20
+ }
21
+ /** Integer text as a number (unsafe ones included, refused by the caller), else the text itself. */
22
+ function integerTextValue(text) {
23
+ const parsed = require_money.parseDecimal(text, "integer");
24
+ return parsed === null ? text : Number(parsed.units);
25
+ }
26
+ /**
27
+ * ISO minor units at the display digits (or `digits`) as Money. The value must be a safe
28
+ * integer (number or integer text). With `digits` above the storage exponent the value must
29
+ * land on a whole storage unit, else `precision`.
30
+ */
31
+ function fromIsoMinor(value, currency, options = {}) {
32
+ const info = require_money.resolveCurrency(currency, { allowHistoric: true });
33
+ const integer = typeof value === "string" ? integerTextValue(value) : value;
34
+ if (typeof integer !== "number" || !Number.isSafeInteger(integer)) throw new require_money.MoneyError("amount_invalid", `ISO minor amount must be a safe integer, got ${require_money.describeValue(value)}`);
35
+ const digits = options.digits ?? info.displayDigits;
36
+ if (![
37
+ 0,
38
+ 2,
39
+ 3
40
+ ].includes(digits)) throw new require_money.MoneyError("amount_invalid", `digits must be 0, 2 or 3, got ${require_money.describeValue(digits)}`);
41
+ const exponent = require_money.storageExponent(info);
42
+ if (digits <= exponent) return require_money.boundedMoney(BigInt(integer) * isoMinorFactor(info, digits), info);
43
+ const excess = require_money.pow10(digits - exponent);
44
+ if (BigInt(integer) % excess !== 0n) throw new require_money.MoneyError("precision", `${integer} at ${digits} digits is not a whole ${info.code} storage unit`);
45
+ return require_money.boundedMoney(BigInt(integer) / excess, info);
46
+ }
47
+ //#endregion
48
+ Object.defineProperty(exports, "fromIsoMinor", {
49
+ enumerable: true,
50
+ get: function() {
51
+ return fromIsoMinor;
52
+ }
53
+ });
54
+ Object.defineProperty(exports, "isoMinorFactor", {
55
+ enumerable: true,
56
+ get: function() {
57
+ return isoMinorFactor;
58
+ }
59
+ });
60
+ Object.defineProperty(exports, "toIsoMinor", {
61
+ enumerable: true,
62
+ get: function() {
63
+ return toIsoMinor;
64
+ }
65
+ });
@@ -0,0 +1,48 @@
1
+ import { E as resolveCurrency, Q as describeValue, Y as mulDiv, Z as MoneyError, ct as pow10, k as storageExponent, s as storedDecimal, st as parseDecimal, t as boundedMoney } from "./money-CIgELekG.js";
2
+ //#region src/iso-minor.ts
3
+ /**
4
+ * Internal: stored units per ISO minor unit at `digits`, `storageScale / 10^digits` (100 for
5
+ * a zero-digit count on a x100 currency, 1 when the digits match the storage exponent).
6
+ * `digits` above the storage exponent has no whole factor and throws `precision`.
7
+ */
8
+ function isoMinorFactor(info, digits) {
9
+ if (digits > storageExponent(info)) throw new MoneyError("precision", `${info.code} stores ${storageExponent(info)} implied decimals, fewer than ${digits}`);
10
+ return BigInt(info.storageScale) / pow10(digits);
11
+ }
12
+ /**
13
+ * ISO minor units at the display digits: `round(major x 10^displayDigits)` with `rounding`
14
+ * (default half-up). JPY 150000 gives 1500, KWD 1005 gives 1005, IQD 10000 gives 10, HUF
15
+ * 435050 gives 4351. Not for payment providers (use `/wire`).
16
+ */
17
+ function toIsoMinor(m, options = {}) {
18
+ const { info } = storedDecimal(m);
19
+ return Number(mulDiv(BigInt(m.amount), 1n, isoMinorFactor(info, info.displayDigits), options.rounding ?? "half-up"));
20
+ }
21
+ /** Integer text as a number (unsafe ones included, refused by the caller), else the text itself. */
22
+ function integerTextValue(text) {
23
+ const parsed = parseDecimal(text, "integer");
24
+ return parsed === null ? text : Number(parsed.units);
25
+ }
26
+ /**
27
+ * ISO minor units at the display digits (or `digits`) as Money. The value must be a safe
28
+ * integer (number or integer text). With `digits` above the storage exponent the value must
29
+ * land on a whole storage unit, else `precision`.
30
+ */
31
+ function fromIsoMinor(value, currency, options = {}) {
32
+ const info = resolveCurrency(currency, { allowHistoric: true });
33
+ const integer = typeof value === "string" ? integerTextValue(value) : value;
34
+ if (typeof integer !== "number" || !Number.isSafeInteger(integer)) throw new MoneyError("amount_invalid", `ISO minor amount must be a safe integer, got ${describeValue(value)}`);
35
+ const digits = options.digits ?? info.displayDigits;
36
+ if (![
37
+ 0,
38
+ 2,
39
+ 3
40
+ ].includes(digits)) throw new MoneyError("amount_invalid", `digits must be 0, 2 or 3, got ${describeValue(digits)}`);
41
+ const exponent = storageExponent(info);
42
+ if (digits <= exponent) return boundedMoney(BigInt(integer) * isoMinorFactor(info, digits), info);
43
+ const excess = pow10(digits - exponent);
44
+ if (BigInt(integer) % excess !== 0n) throw new MoneyError("precision", `${integer} at ${digits} digits is not a whole ${info.code} storage unit`);
45
+ return boundedMoney(BigInt(integer) / excess, info);
46
+ }
47
+ //#endregion
48
+ export { isoMinorFactor as n, toIsoMinor as r, fromIsoMinor as t };
@@ -0,0 +1,101 @@
1
+ import { D as sameCurrency, E as resolveCurrency, Q as describeValue, Z as MoneyError, a as money, at as isPositiveDecimal, b as firstCurrency, d as currencyCode, dt as toDecimalText, i as medusaAmountDecimal, o as readStored, r as isStoredAmount, s as storedDecimal, z as decimalOf } from "./money-CIgELekG.js";
2
+ import { t as hasOwnKey } from "./own-D7544D3k.js";
3
+ //#region src/medusa.ts
4
+ const isObject = (value) => typeof value === "object" && value !== null;
5
+ /** Internal: `row['raw_' + key]` when it is not null/undefined, else `row[key]` (undefined for a non-object row). */
6
+ function storedFieldValue(row, key) {
7
+ if (!isObject(row)) return void 0;
8
+ const raw = row[`raw_${key}`];
9
+ return raw !== null && raw !== void 0 ? raw : row[key];
10
+ }
11
+ function readStoredField(row, key, currency, options = {}) {
12
+ return readStored(storedFieldValue(row, key), currency, {
13
+ ...options,
14
+ field: options.field ?? key
15
+ });
16
+ }
17
+ function readStoredDecimal(raw, options = {}) {
18
+ const value = medusaAmountDecimal(raw);
19
+ if (value && (options.signed !== false || value.units >= 0n)) return toDecimalText(value);
20
+ if (options.mode === "lenient") return null;
21
+ throw new MoneyError("amount_invalid", `Invalid stored amount: ${describeValue(raw)}`, { field: options.field });
22
+ }
23
+ /**
24
+ * A variant's `calculated_price` (a number, or an object read through
25
+ * `raw_calculated_amount` / `calculated_amount`) as Money in
26
+ * `firstCurrency(calculated_price.currency_code, fallbackCurrency)`. Null on anything
27
+ * missing or unreadable.
28
+ */
29
+ function readCalculatedPrice(variant, fallbackCurrency) {
30
+ const price = isObject(variant) ? variant.calculated_price : void 0;
31
+ const priced = isObject(price) ? price : void 0;
32
+ let currency;
33
+ try {
34
+ currency = firstCurrency(priced?.currency_code, fallbackCurrency);
35
+ } catch {
36
+ return null;
37
+ }
38
+ return priced ? readStoredField(priced, "calculated_amount", currency, { mode: "lenient" }) : readStored(price, currency, { mode: "lenient" });
39
+ }
40
+ /**
41
+ * `{ value, precision }` for a Medusa raw column: `value` is plain decimal text, never an
42
+ * exponent (`1e21` gives `'1000000000000000000000'`). NaN and Infinity throw `amount_invalid`.
43
+ */
44
+ function toMedusaRaw(value, precision = 20) {
45
+ if (!Number.isSafeInteger(precision) || precision < 1) throw new MoneyError("amount_invalid", `precision must be a positive integer, got ${describeValue(precision)}`);
46
+ let decimal;
47
+ if (isObject(value)) {
48
+ storedDecimal(value);
49
+ decimal = {
50
+ units: BigInt(value.amount),
51
+ scale: 0
52
+ };
53
+ } else decimal = decimalOf(value);
54
+ return {
55
+ value: toDecimalText(decimal),
56
+ precision
57
+ };
58
+ }
59
+ /** A Money for a Medusa amount input: `'0'` for zero (Medusa drops numeric 0 on order-edit updates), else the number. */
60
+ function toMedusaAmountInput(m) {
61
+ storedDecimal(m);
62
+ return m.amount === 0 ? "0" : m.amount;
63
+ }
64
+ /**
65
+ * Validates an object of `code -> stored amount` (keys through `currencyCode`, values
66
+ * non-negative safe integers), upper-cases the keys and freezes it. A key given twice in
67
+ * different cases throws `currency_invalid`.
68
+ */
69
+ function moneyByCurrency(input) {
70
+ if (!isObject(input) || Array.isArray(input)) throw new MoneyError("amount_invalid", `Expected an object of currency code to stored amount, got ${describeValue(input)}`);
71
+ const out = {};
72
+ for (const key of Object.keys(input)) {
73
+ const code = currencyCode(key, { field: key });
74
+ if (hasOwnKey(out, code)) throw new MoneyError("currency_invalid", `${code} is given more than once`, { field: key });
75
+ const amount = input[key];
76
+ if (!isStoredAmount(amount)) throw new MoneyError("amount_invalid", `Stored amount must be a non-negative safe integer, got ${describeValue(amount)}`, { field: key });
77
+ out[code] = amount === 0 ? 0 : amount;
78
+ }
79
+ return Object.freeze(out);
80
+ }
81
+ /**
82
+ * The amount for `currency` from a MoneyByCurrency or a Medusa price list (base prices only:
83
+ * rows with a `price_list_id` are skipped). Exact currency match, any case; the amount is read
84
+ * strictly. Null when there is none.
85
+ */
86
+ function moneyFor(source, currency) {
87
+ const info = resolveCurrency(currency, { allowHistoric: true });
88
+ if (Array.isArray(source)) {
89
+ const row = source.find((p) => isObject(p) && (p.price_list_id === null || p.price_list_id === void 0) && sameCurrency(p.currency_code, info.code));
90
+ return row ? readStored(row.amount, info.code, { field: "amount" }) : null;
91
+ }
92
+ const map = source;
93
+ return hasOwnKey(map, info.code) ? money(map[info.code], info.code) : null;
94
+ }
95
+ /** Whether unknown Medusa input holds an amount above zero. `''`, null and garbage are false, never a throw. */
96
+ function isPositiveAmount(raw) {
97
+ const value = medusaAmountDecimal(raw);
98
+ return value !== null && isPositiveDecimal(value);
99
+ }
100
+ //#endregion
101
+ export { readStoredDecimal as a, toMedusaAmountInput as c, readCalculatedPrice as i, toMedusaRaw as l, moneyByCurrency as n, readStoredField as o, moneyFor as r, storedFieldValue as s, isPositiveAmount as t };
@@ -0,0 +1,78 @@
1
+ import { L as DecimalText, a as StoredAmount, i as ReadStoredOptions, r as Money } from "./money-CbhsT0fB.cjs";
2
+ //#region src/medusa.d.ts
3
+ /**
4
+ * `row['raw_' + key]` when it is not null/undefined (a failure to read it is final: no
5
+ * fallback to the lossy plain key), else `row[key]`, read like `readStored`.
6
+ */
7
+ declare function readStoredField(row: unknown, key: string, currency: string, options: ReadStoredOptions & {
8
+ mode: 'lenient';
9
+ }): Money | null;
10
+ declare function readStoredField(row: unknown, key: string, currency: string, options?: ReadStoredOptions & {
11
+ mode?: 'strict';
12
+ }): Money;
13
+ declare function readStoredField(row: unknown, key: string, currency: string, options?: ReadStoredOptions): Money | null;
14
+ interface ReadStoredDecimalOptions {
15
+ /** `'strict'` (default) throws `amount_invalid`; `'lenient'` returns null. Never 0. */
16
+ mode?: 'strict' | 'lenient';
17
+ /** Allow negative values. Default true. */
18
+ signed?: boolean;
19
+ /** Names the input field in errors. */
20
+ field?: string;
21
+ }
22
+ /**
23
+ * Like `readStored` but keeps fractions (Medusa fractional totals, ledger literals) and needs
24
+ * no currency: the canonical DecimalText (`{ value: '107.81750000000000000000' }` gives
25
+ * `'107.8175'`). Same shape precedence.
26
+ */
27
+ declare function readStoredDecimal(raw: unknown, options: ReadStoredDecimalOptions & {
28
+ mode: 'lenient';
29
+ }): DecimalText | null;
30
+ declare function readStoredDecimal(raw: unknown, options?: ReadStoredDecimalOptions & {
31
+ mode?: 'strict';
32
+ }): DecimalText;
33
+ declare function readStoredDecimal(raw: unknown, options?: ReadStoredDecimalOptions): DecimalText | null;
34
+ /**
35
+ * A variant's `calculated_price` (a number, or an object read through
36
+ * `raw_calculated_amount` / `calculated_amount`) as Money in
37
+ * `firstCurrency(calculated_price.currency_code, fallbackCurrency)`. Null on anything
38
+ * missing or unreadable.
39
+ */
40
+ declare function readCalculatedPrice(variant: unknown, fallbackCurrency?: string): Money | null;
41
+ /** Medusa's raw amount column shape. */
42
+ interface MedusaRaw {
43
+ readonly value: string;
44
+ readonly precision: number;
45
+ }
46
+ /**
47
+ * `{ value, precision }` for a Medusa raw column: `value` is plain decimal text, never an
48
+ * exponent (`1e21` gives `'1000000000000000000000'`). NaN and Infinity throw `amount_invalid`.
49
+ */
50
+ declare function toMedusaRaw(value: Money | DecimalText | number | bigint, precision?: number): MedusaRaw;
51
+ /** A Money for a Medusa amount input: `'0'` for zero (Medusa drops numeric 0 on order-edit updates), else the number. */
52
+ declare function toMedusaAmountInput(m: Money): number | string;
53
+ /** A per-currency setting: upper-case currency code to stored amount. Build one with `moneyByCurrency`. */
54
+ type MoneyByCurrency = {
55
+ readonly [code: string]: StoredAmount;
56
+ };
57
+ /**
58
+ * Validates an object of `code -> stored amount` (keys through `currencyCode`, values
59
+ * non-negative safe integers), upper-cases the keys and freezes it. A key given twice in
60
+ * different cases throws `currency_invalid`.
61
+ */
62
+ declare function moneyByCurrency(input: unknown): MoneyByCurrency;
63
+ /** A Medusa price row, or anything shaped like one. */
64
+ interface PriceLike {
65
+ readonly amount: unknown;
66
+ readonly currency_code: string;
67
+ readonly price_list_id?: string | null;
68
+ }
69
+ /**
70
+ * The amount for `currency` from a MoneyByCurrency or a Medusa price list (base prices only:
71
+ * rows with a `price_list_id` are skipped). Exact currency match, any case; the amount is read
72
+ * strictly. Null when there is none.
73
+ */
74
+ declare function moneyFor(source: MoneyByCurrency | readonly PriceLike[], currency: string): Money | null;
75
+ /** Whether unknown Medusa input holds an amount above zero. `''`, null and garbage are false, never a throw. */
76
+ declare function isPositiveAmount(raw: unknown): boolean;
77
+ //#endregion
78
+ export { isPositiveAmount as a, readCalculatedPrice as c, toMedusaAmountInput as d, toMedusaRaw as f, ReadStoredDecimalOptions as i, readStoredDecimal as l, MoneyByCurrency as n, moneyByCurrency as o, PriceLike as r, moneyFor as s, MedusaRaw as t, readStoredField as u };
@@ -0,0 +1,154 @@
1
+ const require_money = require("./money-D5-vlv0h.cjs");
2
+ const require_own = require("./own-oP9DXFWv.cjs");
3
+ //#region src/medusa.ts
4
+ const isObject = (value) => typeof value === "object" && value !== null;
5
+ /** Internal: `row['raw_' + key]` when it is not null/undefined, else `row[key]` (undefined for a non-object row). */
6
+ function storedFieldValue(row, key) {
7
+ if (!isObject(row)) return void 0;
8
+ const raw = row[`raw_${key}`];
9
+ return raw !== null && raw !== void 0 ? raw : row[key];
10
+ }
11
+ function readStoredField(row, key, currency, options = {}) {
12
+ return require_money.readStored(storedFieldValue(row, key), currency, {
13
+ ...options,
14
+ field: options.field ?? key
15
+ });
16
+ }
17
+ function readStoredDecimal(raw, options = {}) {
18
+ const value = require_money.medusaAmountDecimal(raw);
19
+ if (value && (options.signed !== false || value.units >= 0n)) return require_money.toDecimalText(value);
20
+ if (options.mode === "lenient") return null;
21
+ throw new require_money.MoneyError("amount_invalid", `Invalid stored amount: ${require_money.describeValue(raw)}`, { field: options.field });
22
+ }
23
+ /**
24
+ * A variant's `calculated_price` (a number, or an object read through
25
+ * `raw_calculated_amount` / `calculated_amount`) as Money in
26
+ * `firstCurrency(calculated_price.currency_code, fallbackCurrency)`. Null on anything
27
+ * missing or unreadable.
28
+ */
29
+ function readCalculatedPrice(variant, fallbackCurrency) {
30
+ const price = isObject(variant) ? variant.calculated_price : void 0;
31
+ const priced = isObject(price) ? price : void 0;
32
+ let currency;
33
+ try {
34
+ currency = require_money.firstCurrency(priced?.currency_code, fallbackCurrency);
35
+ } catch {
36
+ return null;
37
+ }
38
+ return priced ? readStoredField(priced, "calculated_amount", currency, { mode: "lenient" }) : require_money.readStored(price, currency, { mode: "lenient" });
39
+ }
40
+ /**
41
+ * `{ value, precision }` for a Medusa raw column: `value` is plain decimal text, never an
42
+ * exponent (`1e21` gives `'1000000000000000000000'`). NaN and Infinity throw `amount_invalid`.
43
+ */
44
+ function toMedusaRaw(value, precision = 20) {
45
+ if (!Number.isSafeInteger(precision) || precision < 1) throw new require_money.MoneyError("amount_invalid", `precision must be a positive integer, got ${require_money.describeValue(precision)}`);
46
+ let decimal;
47
+ if (isObject(value)) {
48
+ require_money.storedDecimal(value);
49
+ decimal = {
50
+ units: BigInt(value.amount),
51
+ scale: 0
52
+ };
53
+ } else decimal = require_money.decimalOf(value);
54
+ return {
55
+ value: require_money.toDecimalText(decimal),
56
+ precision
57
+ };
58
+ }
59
+ /** A Money for a Medusa amount input: `'0'` for zero (Medusa drops numeric 0 on order-edit updates), else the number. */
60
+ function toMedusaAmountInput(m) {
61
+ require_money.storedDecimal(m);
62
+ return m.amount === 0 ? "0" : m.amount;
63
+ }
64
+ /**
65
+ * Validates an object of `code -> stored amount` (keys through `currencyCode`, values
66
+ * non-negative safe integers), upper-cases the keys and freezes it. A key given twice in
67
+ * different cases throws `currency_invalid`.
68
+ */
69
+ function moneyByCurrency(input) {
70
+ if (!isObject(input) || Array.isArray(input)) throw new require_money.MoneyError("amount_invalid", `Expected an object of currency code to stored amount, got ${require_money.describeValue(input)}`);
71
+ const out = {};
72
+ for (const key of Object.keys(input)) {
73
+ const code = require_money.currencyCode(key, { field: key });
74
+ if (require_own.hasOwnKey(out, code)) throw new require_money.MoneyError("currency_invalid", `${code} is given more than once`, { field: key });
75
+ const amount = input[key];
76
+ if (!require_money.isStoredAmount(amount)) throw new require_money.MoneyError("amount_invalid", `Stored amount must be a non-negative safe integer, got ${require_money.describeValue(amount)}`, { field: key });
77
+ out[code] = amount === 0 ? 0 : amount;
78
+ }
79
+ return Object.freeze(out);
80
+ }
81
+ /**
82
+ * The amount for `currency` from a MoneyByCurrency or a Medusa price list (base prices only:
83
+ * rows with a `price_list_id` are skipped). Exact currency match, any case; the amount is read
84
+ * strictly. Null when there is none.
85
+ */
86
+ function moneyFor(source, currency) {
87
+ const info = require_money.resolveCurrency(currency, { allowHistoric: true });
88
+ if (Array.isArray(source)) {
89
+ const row = source.find((p) => isObject(p) && (p.price_list_id === null || p.price_list_id === void 0) && require_money.sameCurrency(p.currency_code, info.code));
90
+ return row ? require_money.readStored(row.amount, info.code, { field: "amount" }) : null;
91
+ }
92
+ const map = source;
93
+ return require_own.hasOwnKey(map, info.code) ? require_money.money(map[info.code], info.code) : null;
94
+ }
95
+ /** Whether unknown Medusa input holds an amount above zero. `''`, null and garbage are false, never a throw. */
96
+ function isPositiveAmount(raw) {
97
+ const value = require_money.medusaAmountDecimal(raw);
98
+ return value !== null && require_money.isPositiveDecimal(value);
99
+ }
100
+ //#endregion
101
+ Object.defineProperty(exports, "isPositiveAmount", {
102
+ enumerable: true,
103
+ get: function() {
104
+ return isPositiveAmount;
105
+ }
106
+ });
107
+ Object.defineProperty(exports, "moneyByCurrency", {
108
+ enumerable: true,
109
+ get: function() {
110
+ return moneyByCurrency;
111
+ }
112
+ });
113
+ Object.defineProperty(exports, "moneyFor", {
114
+ enumerable: true,
115
+ get: function() {
116
+ return moneyFor;
117
+ }
118
+ });
119
+ Object.defineProperty(exports, "readCalculatedPrice", {
120
+ enumerable: true,
121
+ get: function() {
122
+ return readCalculatedPrice;
123
+ }
124
+ });
125
+ Object.defineProperty(exports, "readStoredDecimal", {
126
+ enumerable: true,
127
+ get: function() {
128
+ return readStoredDecimal;
129
+ }
130
+ });
131
+ Object.defineProperty(exports, "readStoredField", {
132
+ enumerable: true,
133
+ get: function() {
134
+ return readStoredField;
135
+ }
136
+ });
137
+ Object.defineProperty(exports, "storedFieldValue", {
138
+ enumerable: true,
139
+ get: function() {
140
+ return storedFieldValue;
141
+ }
142
+ });
143
+ Object.defineProperty(exports, "toMedusaAmountInput", {
144
+ enumerable: true,
145
+ get: function() {
146
+ return toMedusaAmountInput;
147
+ }
148
+ });
149
+ Object.defineProperty(exports, "toMedusaRaw", {
150
+ enumerable: true,
151
+ get: function() {
152
+ return toMedusaRaw;
153
+ }
154
+ });