@amboras-dev/capability-kit 0.1.0 → 0.2.1
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.
- package/README.md +15 -5
- package/dist/index.cjs +82 -101
- package/dist/index.d.cts +23 -22
- package/dist/index.d.ts +23 -22
- package/dist/index.js +75 -94
- package/package.json +58 -55
package/README.md
CHANGED
|
@@ -5,7 +5,8 @@ and the orchestrator (which exposes them as AI tools). One definition per
|
|
|
5
5
|
merchant action: id, zod input/output, policy and agent text. The kit checks it
|
|
6
6
|
once, converts money at one boundary, answers errors in one shape and emits a
|
|
7
7
|
hashed manifest the other repo re-checks on load. CommonJS + ESM + types; Node >= 20 and
|
|
8
|
-
browsers.
|
|
8
|
+
browsers. One runtime dependency, `@amboras-dev/money` (the storage rule, conversion
|
|
9
|
+
and money view; the kit pins its exact version), and the `zod` peer (`^3.25.76 || ^4.0.0`,
|
|
9
10
|
imported only as `zod/v4`; zod 3.25.0 ships without `dist/` and cannot load `zod/v4`).
|
|
10
11
|
|
|
11
12
|
```ts
|
|
@@ -83,18 +84,27 @@ count, or a count that is not a non-negative integer.
|
|
|
83
84
|
- **Major units at every boundary.** `money()` is the only money field type; its
|
|
84
85
|
description is the one unit sentence. Storage is Medusa's: ×1000 for KWD, BHD,
|
|
85
86
|
OMR, TND, JOD, IQD, LYD and ×100 for everything else, zero-decimal codes
|
|
86
|
-
included. The
|
|
87
|
-
|
|
87
|
+
included. The rule has one owner, `@amboras-dev/money`: `storageScale`,
|
|
88
|
+
`fractionDigits`, `toStorageAmount`, `fromStorageAmount` and `moneyView` are thin
|
|
89
|
+
wrappers over its `storageScale`, `storageDigits`, `fromMajor`, `toMajorNumber` and
|
|
90
|
+
`/ai` `moneyView`. Codes are validated by the package's `currencyCode`: an unknown
|
|
91
|
+
code (`ZZZ`) throws `currency_invalid`; retired codes (BGN) still read. A stored
|
|
92
|
+
amount must be a safe integer.
|
|
88
93
|
- **Excess decimals throw, float noise rounds.** `19.99 × 100 = 1998.999…` stores
|
|
89
94
|
1999 and `0.1 + 0.2` stores 30; `19.999 USD` and `5.5 JPY` throw. The digit
|
|
90
95
|
check reads the number's decimal text, so it holds at any magnitude; amounts
|
|
91
96
|
above 2^46 units of the currency's precision (USD 703 billion) refuse as too large.
|
|
92
97
|
- **`MoneyError` is an `invalid_input` `CapabilityError`** (rules `money_precision`,
|
|
93
|
-
`money_invalid`, `currency_invalid`)
|
|
98
|
+
`money_invalid`, `currency_invalid`), mapped from the package's `MoneyError` codes
|
|
99
|
+
(`precision` → `money_precision`; `amount_invalid`, `overflow` → `money_invalid`;
|
|
100
|
+
`currency_invalid` → `currency_invalid`). `toStorageAmount(major, currency, field)`
|
|
94
101
|
names the field, so an adapter answers 400 with it. A bad `money()` option is
|
|
95
102
|
a `CapabilityDefinitionError` (boot).
|
|
96
103
|
- **Display digits are pinned**, not read from the runtime's ICU data (HUF/IDR
|
|
97
|
-
differ between Node images).
|
|
104
|
+
differ between Node images). `moneyView` shows the currency's display digits from
|
|
105
|
+
the package registry, widened to keep a finer stored value: HUF 435000 is
|
|
106
|
+
`HUF 4,350` (was `HUF 4,350.00`), HUF 435050 `HUF 4,350.5`, IQD 1500 `IQD 1.5`
|
|
107
|
+
(was `IQD 1.500`); `amount` is always exact.
|
|
98
108
|
- **Chaining on `money()` is safe; `.describe()` is not.** `money()` adds a
|
|
99
109
|
no-op refinement as a brand. zod copies checks into every clone, so the brand
|
|
100
110
|
survives `.positive()`, `.max()`, `.int()`, `.optional()`, `.nullish()`, even
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let zod_v4 = require("zod/v4");
|
|
3
|
+
let _amboras_dev_money = require("@amboras-dev/money");
|
|
4
|
+
let _amboras_dev_money_ai = require("@amboras-dev/money/ai");
|
|
3
5
|
//#region src/canonical-json.ts
|
|
4
6
|
function serialize(value, seen) {
|
|
5
7
|
if (value !== null && typeof value === "object" && typeof value.toJSON === "function") value = value.toJSON();
|
|
@@ -197,38 +199,6 @@ function isRole(value) {
|
|
|
197
199
|
}
|
|
198
200
|
//#endregion
|
|
199
201
|
//#region src/money.ts
|
|
200
|
-
const ZERO_DECIMAL = /* @__PURE__ */ new Set([
|
|
201
|
-
"JPY",
|
|
202
|
-
"KRW",
|
|
203
|
-
"VND",
|
|
204
|
-
"CLP",
|
|
205
|
-
"PYG",
|
|
206
|
-
"XAF",
|
|
207
|
-
"XOF",
|
|
208
|
-
"BIF",
|
|
209
|
-
"DJF",
|
|
210
|
-
"GNF",
|
|
211
|
-
"ISK",
|
|
212
|
-
"KMF",
|
|
213
|
-
"MGA",
|
|
214
|
-
"RWF",
|
|
215
|
-
"UGX",
|
|
216
|
-
"VUV",
|
|
217
|
-
"XPF"
|
|
218
|
-
]);
|
|
219
|
-
const THREE_DECIMAL = /* @__PURE__ */ new Set([
|
|
220
|
-
"KWD",
|
|
221
|
-
"BHD",
|
|
222
|
-
"OMR",
|
|
223
|
-
"TND",
|
|
224
|
-
"JOD",
|
|
225
|
-
"IQD",
|
|
226
|
-
"LYD"
|
|
227
|
-
]);
|
|
228
|
-
/** The one unit sentence every money field carries, for the model and for people. */
|
|
229
|
-
const MONEY_UNIT_SENTENCE = "Amount in normal currency units as the merchant says it (99 means 99.00; 1.5 means 1.50). Never cents or minor units.";
|
|
230
|
-
/** JSON Schema keyword marking a money field. */
|
|
231
|
-
const MONEY_META_KEY = "x-amboras-money";
|
|
232
202
|
/**
|
|
233
203
|
* A bad amount or currency code. It is an `invalid_input` CapabilityError, so an
|
|
234
204
|
* adapter that maps CapabilityError answers 400 with the rule (and the field,
|
|
@@ -276,7 +246,7 @@ function money(opts) {
|
|
|
276
246
|
const { exclusiveMinimum, max } = opts;
|
|
277
247
|
if (exclusiveMinimum !== void 0 && !isBound(exclusiveMinimum)) throw new CapabilityDefinitionError("money(): exclusiveMinimum must be a finite number ≥ 0");
|
|
278
248
|
if (max !== void 0 && (!isBound(max) || max <= (exclusiveMinimum ?? -1))) throw new CapabilityDefinitionError("money(): max must be a finite number ≥ 0 and above exclusiveMinimum");
|
|
279
|
-
const description = opts.describe ? `${opts.describe.trim()} ${MONEY_UNIT_SENTENCE}` : MONEY_UNIT_SENTENCE;
|
|
249
|
+
const description = opts.describe ? `${opts.describe.trim()} ${_amboras_dev_money_ai.MONEY_UNIT_SENTENCE}` : _amboras_dev_money_ai.MONEY_UNIT_SENTENCE;
|
|
280
250
|
let schema = exclusiveMinimum === void 0 ? zod_v4.z.number().min(0) : zod_v4.z.number().gt(exclusiveMinimum);
|
|
281
251
|
if (max !== void 0) schema = schema.max(max);
|
|
282
252
|
schema = schema.refine(alwaysValid);
|
|
@@ -287,64 +257,82 @@ function money(opts) {
|
|
|
287
257
|
});
|
|
288
258
|
return schema.meta({
|
|
289
259
|
description,
|
|
290
|
-
[MONEY_META_KEY]: marker
|
|
260
|
+
[_amboras_dev_money_ai.MONEY_META_KEY]: marker
|
|
291
261
|
});
|
|
292
262
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
263
|
+
const RULE_FOR_CODE = new Map(Object.entries({
|
|
264
|
+
precision: "money_precision",
|
|
265
|
+
amount_invalid: "money_invalid",
|
|
266
|
+
overflow: "money_invalid",
|
|
267
|
+
parse: "money_invalid",
|
|
268
|
+
rate_invalid: "money_invalid",
|
|
269
|
+
wire_refused: "money_invalid",
|
|
270
|
+
currency_invalid: "currency_invalid",
|
|
271
|
+
currency_missing: "currency_invalid",
|
|
272
|
+
currency_mismatch: "currency_invalid",
|
|
273
|
+
wire_unsupported: "currency_invalid"
|
|
274
|
+
}));
|
|
275
|
+
/** The caller's code as a known currency (`currencyCode` from @amboras-dev/money), or a kit `currency_invalid`. */
|
|
276
|
+
function kitCurrency(currency) {
|
|
277
|
+
try {
|
|
278
|
+
return (0, _amboras_dev_money.currencyCode)(currency);
|
|
279
|
+
} catch (error) {
|
|
280
|
+
throw toCapabilityMoneyError(error);
|
|
281
|
+
}
|
|
296
282
|
}
|
|
297
|
-
/**
|
|
283
|
+
/**
|
|
284
|
+
* Internal: an error from @amboras-dev/money as the kit's MoneyError, keyed by its `code`
|
|
285
|
+
* (not `instanceof`, so a second copy of the package still maps). Anything else (never
|
|
286
|
+
* expected) is `money_invalid`.
|
|
287
|
+
*/
|
|
288
|
+
function toCapabilityMoneyError(error, field) {
|
|
289
|
+
const code = error?.code;
|
|
290
|
+
const rule = RULE_FOR_CODE.get(code) ?? "money_invalid";
|
|
291
|
+
return new MoneyError(error instanceof Error ? error.message : String(error), rule, field);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Storage digits (`storageDigits` in @amboras-dev/money): 0 for JPY/KRW/VND…, 3 for
|
|
295
|
+
* KWD/BHD/OMR/TND/JOD/IQD/LYD, else 2. An unknown code throws `currency_invalid`.
|
|
296
|
+
*/
|
|
298
297
|
function fractionDigits(currency) {
|
|
299
|
-
|
|
300
|
-
if (ZERO_DECIMAL.has(code)) return 0;
|
|
301
|
-
if (THREE_DECIMAL.has(code)) return 3;
|
|
302
|
-
return 2;
|
|
298
|
+
return (0, _amboras_dev_money.storageDigits)(kitCurrency(currency));
|
|
303
299
|
}
|
|
304
300
|
/**
|
|
305
|
-
* Amboras storage rule: ×1000 for the seven
|
|
306
|
-
* other code INCLUDING zero-decimal ones (¥5 is
|
|
307
|
-
*
|
|
301
|
+
* Amboras storage rule (`storageScale` in @amboras-dev/money): ×1000 for the seven
|
|
302
|
+
* three-decimal codes, ×100 for every other code INCLUDING zero-decimal ones (¥5 is
|
|
303
|
+
* stored as 500). An unknown code throws `currency_invalid`.
|
|
308
304
|
*/
|
|
309
305
|
function storageScale(currency) {
|
|
310
|
-
return
|
|
311
|
-
}
|
|
312
|
-
const MAX_UNITS = 2 ** 46;
|
|
313
|
-
/** Decimal places in the shortest text form of `n` (what JSON carries): 19.99 → 2, 1e-7 → 7, 1.5e+21 → 0. */
|
|
314
|
-
function decimalPlaces(n) {
|
|
315
|
-
const [mantissa, exponent = "0"] = String(Math.abs(n)).split("e");
|
|
316
|
-
const fraction = mantissa.split(".")[1] ?? "";
|
|
317
|
-
return Math.max(0, fraction.length - Number(exponent));
|
|
306
|
+
return (0, _amboras_dev_money.storageScale)(kitCurrency(currency));
|
|
318
307
|
}
|
|
319
308
|
/**
|
|
320
|
-
* Major → stored minor integer
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
* (exact at any magnitude), or when it is within float noise of such an amount
|
|
327
|
-
* (0.1 + 0.2 → 0.30). Noise is bounded absolutely, so a real extra digit is never
|
|
328
|
-
* rounded away, however large the amount.
|
|
309
|
+
* Major → stored minor integer: `fromMajor(major, currency).amount` from
|
|
310
|
+
* @amboras-dev/money. Throws MoneyError (`invalid_input`) when the amount has more
|
|
311
|
+
* fraction digits than the currency allows (19.999 USD, 5.5 JPY), is not a finite
|
|
312
|
+
* number, or does not fit (2^46 units of the currency's digits). Float noise is
|
|
313
|
+
* accepted (0.1 + 0.2 → 0.30); a real extra digit never is. Pass `field` to name the
|
|
314
|
+
* input field in the error.
|
|
329
315
|
*/
|
|
330
316
|
function toStorageAmount(major, currency, field) {
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (!(decimalPlaces(major) <= digits) && noise > Math.min(8 * Number.EPSILON * Math.max(1, Math.abs(inDigits)), 1e-6)) throw new MoneyError(`${major} has more than ${digits} decimal places, the most ${code} allows`, "money_precision", field);
|
|
339
|
-
const stored = whole * (scale / 10 ** digits);
|
|
340
|
-
if (Math.abs(whole) > MAX_UNITS || !Number.isSafeInteger(stored)) throw new MoneyError(`${major} ${code} is too large to store`, "money_invalid", field);
|
|
341
|
-
return stored === 0 ? 0 : stored;
|
|
317
|
+
const code = kitCurrency(currency);
|
|
318
|
+
if (typeof major !== "number") throw new MoneyError(`Amount must be a finite number, got ${String(major)}`, "money_invalid", field);
|
|
319
|
+
try {
|
|
320
|
+
return (0, _amboras_dev_money.fromMajor)(major, code).amount;
|
|
321
|
+
} catch (error) {
|
|
322
|
+
throw toCapabilityMoneyError(error, field);
|
|
323
|
+
}
|
|
342
324
|
}
|
|
343
|
-
/**
|
|
325
|
+
/**
|
|
326
|
+
* Stored minor amount → major units: `toMajorNumber(money(minor, currency))` from
|
|
327
|
+
* @amboras-dev/money. The stored amount must be a safe integer.
|
|
328
|
+
*/
|
|
344
329
|
function fromStorageAmount(minor, currency) {
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
|
|
330
|
+
const code = kitCurrency(currency);
|
|
331
|
+
try {
|
|
332
|
+
return (0, _amboras_dev_money.toMajorNumber)((0, _amboras_dev_money.money)(minor, code));
|
|
333
|
+
} catch (error) {
|
|
334
|
+
throw toCapabilityMoneyError(error);
|
|
335
|
+
}
|
|
348
336
|
}
|
|
349
337
|
/** Output schema for a MoneyView (what `moneyView` returns), for capability outputs. */
|
|
350
338
|
const moneyViewSchema = zod_v4.z.object({
|
|
@@ -353,25 +341,18 @@ const moneyViewSchema = zod_v4.z.object({
|
|
|
353
341
|
display: zod_v4.z.string().describe("Formatted for people, e.g. \"$19.99\".")
|
|
354
342
|
});
|
|
355
343
|
/**
|
|
356
|
-
* A stored amount as the merchant reads it
|
|
357
|
-
*
|
|
358
|
-
*
|
|
344
|
+
* A stored amount as the merchant reads it: `moneyView` from @amboras-dev/money/ai.
|
|
345
|
+
* `amount` is exact; `display` shows the currency's display digits, widened to keep a
|
|
346
|
+
* stored value finer than them (¥5.5 stays visible, HUF 435000 is `HUF 4,350`). An
|
|
347
|
+
* unknown code throws `currency_invalid`.
|
|
359
348
|
*/
|
|
360
349
|
function moneyView(minor, currency) {
|
|
361
|
-
const code =
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
currency: code,
|
|
368
|
-
display: new Intl.NumberFormat("en", {
|
|
369
|
-
style: "currency",
|
|
370
|
-
currency: code,
|
|
371
|
-
minimumFractionDigits: digits,
|
|
372
|
-
maximumFractionDigits: Math.max(digits, scaleDigits)
|
|
373
|
-
}).format(amount)
|
|
374
|
-
};
|
|
350
|
+
const code = kitCurrency(currency);
|
|
351
|
+
try {
|
|
352
|
+
return (0, _amboras_dev_money_ai.moneyView)((0, _amboras_dev_money.money)(minor, code));
|
|
353
|
+
} catch (error) {
|
|
354
|
+
throw toCapabilityMoneyError(error);
|
|
355
|
+
}
|
|
375
356
|
}
|
|
376
357
|
//#endregion
|
|
377
358
|
//#region src/json-schema.ts
|
|
@@ -389,7 +370,7 @@ function toJsonSchema(schema, io) {
|
|
|
389
370
|
const brand = moneyBrandOf(ctx.zodSchema);
|
|
390
371
|
if (!brand) return;
|
|
391
372
|
const node = ctx.jsonSchema;
|
|
392
|
-
node[MONEY_META_KEY] = { ...brand.marker };
|
|
373
|
+
node[_amboras_dev_money_ai.MONEY_META_KEY] = { ...brand.marker };
|
|
393
374
|
if (typeof node.description !== "string") node.description = brand.description;
|
|
394
375
|
}
|
|
395
376
|
});
|
|
@@ -552,11 +533,11 @@ function checkFieldName(id, name, schema) {
|
|
|
552
533
|
}
|
|
553
534
|
function checkMoneyNode(id, input, node) {
|
|
554
535
|
const description = node.description;
|
|
555
|
-
if (typeof description !== "string" || !description.includes(
|
|
556
|
-
const marker = node[MONEY_META_KEY];
|
|
536
|
+
if (typeof description !== "string" || !description.includes(_amboras_dev_money_ai.MONEY_UNIT_SENTENCE)) fail(id, "a money() field lost its unit sentence; pass money({ ..., describe }) instead of .describe()/.meta()");
|
|
537
|
+
const marker = node[_amboras_dev_money_ai.MONEY_META_KEY];
|
|
557
538
|
const field = isRecord(marker) ? marker.currencyField : void 0;
|
|
558
539
|
if (isRecord(marker) && marker.currency === "store" && field === void 0) return;
|
|
559
|
-
if (typeof field !== "string") fail(id, `a money() field has a malformed ${MONEY_META_KEY} marker`);
|
|
540
|
+
if (typeof field !== "string") fail(id, `a money() field has a malformed ${_amboras_dev_money_ai.MONEY_META_KEY} marker`);
|
|
560
541
|
const found = resolveField(input, field);
|
|
561
542
|
if (found.length === 0) fail(id, `money() currencyField "${field}" is not a field at the input root`);
|
|
562
543
|
for (const { parent, name } of found) {
|
|
@@ -578,7 +559,7 @@ function checkInputSchema(id, input) {
|
|
|
578
559
|
const keys = finiteKeys(node);
|
|
579
560
|
if (keys) for (const name of keys) checkFieldName(id, name, node.additionalProperties);
|
|
580
561
|
if (node.additionalProperties !== void 0 && node.additionalProperties !== false && !keys || "patternProperties" in node || "propertyNames" in node && !keys) fail(id, "input objects must declare their keys (no z.record with open keys, z.looseObject or .passthrough())");
|
|
581
|
-
if (
|
|
562
|
+
if (_amboras_dev_money_ai.MONEY_META_KEY in node) checkMoneyNode(id, input, node);
|
|
582
563
|
});
|
|
583
564
|
}
|
|
584
565
|
function checkHideFields(id, input, hideFields) {
|
|
@@ -1039,8 +1020,8 @@ exports.CapabilityDefinitionError = CapabilityDefinitionError;
|
|
|
1039
1020
|
exports.CapabilityError = CapabilityError;
|
|
1040
1021
|
exports.CapabilityManifestError = CapabilityManifestError;
|
|
1041
1022
|
exports.IDEMPOTENCY_KEY_PATTERN = IDEMPOTENCY_KEY_PATTERN;
|
|
1042
|
-
exports.MONEY_META_KEY = MONEY_META_KEY;
|
|
1043
|
-
exports.MONEY_UNIT_SENTENCE = MONEY_UNIT_SENTENCE;
|
|
1023
|
+
exports.MONEY_META_KEY = _amboras_dev_money_ai.MONEY_META_KEY;
|
|
1024
|
+
exports.MONEY_UNIT_SENTENCE = _amboras_dev_money_ai.MONEY_UNIT_SENTENCE;
|
|
1044
1025
|
exports.MoneyError = MoneyError;
|
|
1045
1026
|
exports.ROLE_RANK = ROLE_RANK;
|
|
1046
1027
|
exports.areaOf = areaOf;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
|
+
import { MONEY_META_KEY, MONEY_UNIT_SENTENCE } from "@amboras-dev/money/ai";
|
|
2
3
|
//#region src/canonical-json.d.ts
|
|
3
4
|
/** Sorted keys, no whitespace. Throws on BigInt and circular values; `undefined` at the top serializes as `null`. */
|
|
4
5
|
export declare function canonicalJson(v: unknown): string;
|
|
@@ -210,10 +211,6 @@ export declare function emitManifest(defs: readonly AnyCapabilityDefinition[], s
|
|
|
210
211
|
export declare function parseManifest(json: unknown): CapabilityManifest;
|
|
211
212
|
//#endregion
|
|
212
213
|
//#region src/money.d.ts
|
|
213
|
-
/** The one unit sentence every money field carries, for the model and for people. */
|
|
214
|
-
export declare const MONEY_UNIT_SENTENCE = "Amount in normal currency units as the merchant says it (99 means 99.00; 1.5 means 1.50). Never cents or minor units.";
|
|
215
|
-
/** JSON Schema keyword marking a money field. */
|
|
216
|
-
export declare const MONEY_META_KEY = "x-amboras-money";
|
|
217
214
|
/**
|
|
218
215
|
* A bad amount or currency code. It is an `invalid_input` CapabilityError, so an
|
|
219
216
|
* adapter that maps CapabilityError answers 400 with the rule (and the field,
|
|
@@ -250,27 +247,30 @@ type MoneyOptions = MoneyCurrency & {
|
|
|
250
247
|
* rejects: pass `describe` here instead.
|
|
251
248
|
*/
|
|
252
249
|
export declare function money(opts: MoneyOptions): z.ZodNumber;
|
|
253
|
-
/**
|
|
250
|
+
/**
|
|
251
|
+
* Storage digits (`storageDigits` in @amboras-dev/money): 0 for JPY/KRW/VND…, 3 for
|
|
252
|
+
* KWD/BHD/OMR/TND/JOD/IQD/LYD, else 2. An unknown code throws `currency_invalid`.
|
|
253
|
+
*/
|
|
254
254
|
export declare function fractionDigits(currency: string): 0 | 2 | 3;
|
|
255
255
|
/**
|
|
256
|
-
* Amboras storage rule: ×1000 for the seven
|
|
257
|
-
* other code INCLUDING zero-decimal ones (¥5 is
|
|
258
|
-
*
|
|
256
|
+
* Amboras storage rule (`storageScale` in @amboras-dev/money): ×1000 for the seven
|
|
257
|
+
* three-decimal codes, ×100 for every other code INCLUDING zero-decimal ones (¥5 is
|
|
258
|
+
* stored as 500). An unknown code throws `currency_invalid`.
|
|
259
259
|
*/
|
|
260
260
|
export declare function storageScale(currency: string): 100 | 1000;
|
|
261
261
|
/**
|
|
262
|
-
* Major → stored minor integer
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
* (exact at any magnitude), or when it is within float noise of such an amount
|
|
269
|
-
* (0.1 + 0.2 → 0.30). Noise is bounded absolutely, so a real extra digit is never
|
|
270
|
-
* rounded away, however large the amount.
|
|
262
|
+
* Major → stored minor integer: `fromMajor(major, currency).amount` from
|
|
263
|
+
* @amboras-dev/money. Throws MoneyError (`invalid_input`) when the amount has more
|
|
264
|
+
* fraction digits than the currency allows (19.999 USD, 5.5 JPY), is not a finite
|
|
265
|
+
* number, or does not fit (2^46 units of the currency's digits). Float noise is
|
|
266
|
+
* accepted (0.1 + 0.2 → 0.30); a real extra digit never is. Pass `field` to name the
|
|
267
|
+
* input field in the error.
|
|
271
268
|
*/
|
|
272
269
|
export declare function toStorageAmount(major: number, currency: string, field?: string): number;
|
|
273
|
-
/**
|
|
270
|
+
/**
|
|
271
|
+
* Stored minor amount → major units: `toMajorNumber(money(minor, currency))` from
|
|
272
|
+
* @amboras-dev/money. The stored amount must be a safe integer.
|
|
273
|
+
*/
|
|
274
274
|
export declare function fromStorageAmount(minor: number, currency: string): number;
|
|
275
275
|
interface MoneyView {
|
|
276
276
|
amount: number;
|
|
@@ -280,9 +280,10 @@ interface MoneyView {
|
|
|
280
280
|
/** Output schema for a MoneyView (what `moneyView` returns), for capability outputs. */
|
|
281
281
|
export declare const moneyViewSchema: z.ZodType<MoneyView>;
|
|
282
282
|
/**
|
|
283
|
-
* A stored amount as the merchant reads it
|
|
284
|
-
*
|
|
285
|
-
*
|
|
283
|
+
* A stored amount as the merchant reads it: `moneyView` from @amboras-dev/money/ai.
|
|
284
|
+
* `amount` is exact; `display` shows the currency's display digits, widened to keep a
|
|
285
|
+
* stored value finer than them (¥5.5 stays visible, HUF 435000 is `HUF 4,350`). An
|
|
286
|
+
* unknown code throws `currency_invalid`.
|
|
286
287
|
*/
|
|
287
288
|
export declare function moneyView(minor: number, currency: string): MoneyView;
|
|
288
289
|
//#endregion
|
|
@@ -310,4 +311,4 @@ export declare function evaluatePolicy(policy: CapabilityPolicy, ctx: Capability
|
|
|
310
311
|
*/
|
|
311
312
|
export declare function confirmationRequired(policy: Pick<CapabilityPolicy, 'confirm'>, records?: number): boolean;
|
|
312
313
|
//#endregion
|
|
313
|
-
export type
|
|
314
|
+
export { type Actor, type AnyCapabilityDefinition, type Area, type CapabilityAgentSpec, type CapabilityCallContext, type CapabilityDefinition, type CapabilityErrorBody, type CapabilityErrorCode, type CapabilityErrorInit, type CapabilityId, type CapabilityManifest, type CapabilityPolicy, type FromZodErrorOptions, type JsonSchema, MONEY_META_KEY, MONEY_UNIT_SENTENCE, type ManifestEntry, type MoneyCurrency, type MoneyOptions, type MoneyView, type PolicyDecision, type PolicyEnforcement, type Role, type Surface };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
|
+
import { MONEY_META_KEY, MONEY_UNIT_SENTENCE } from "@amboras-dev/money/ai";
|
|
2
3
|
//#region src/canonical-json.d.ts
|
|
3
4
|
/** Sorted keys, no whitespace. Throws on BigInt and circular values; `undefined` at the top serializes as `null`. */
|
|
4
5
|
export declare function canonicalJson(v: unknown): string;
|
|
@@ -210,10 +211,6 @@ export declare function emitManifest(defs: readonly AnyCapabilityDefinition[], s
|
|
|
210
211
|
export declare function parseManifest(json: unknown): CapabilityManifest;
|
|
211
212
|
//#endregion
|
|
212
213
|
//#region src/money.d.ts
|
|
213
|
-
/** The one unit sentence every money field carries, for the model and for people. */
|
|
214
|
-
export declare const MONEY_UNIT_SENTENCE = "Amount in normal currency units as the merchant says it (99 means 99.00; 1.5 means 1.50). Never cents or minor units.";
|
|
215
|
-
/** JSON Schema keyword marking a money field. */
|
|
216
|
-
export declare const MONEY_META_KEY = "x-amboras-money";
|
|
217
214
|
/**
|
|
218
215
|
* A bad amount or currency code. It is an `invalid_input` CapabilityError, so an
|
|
219
216
|
* adapter that maps CapabilityError answers 400 with the rule (and the field,
|
|
@@ -250,27 +247,30 @@ type MoneyOptions = MoneyCurrency & {
|
|
|
250
247
|
* rejects: pass `describe` here instead.
|
|
251
248
|
*/
|
|
252
249
|
export declare function money(opts: MoneyOptions): z.ZodNumber;
|
|
253
|
-
/**
|
|
250
|
+
/**
|
|
251
|
+
* Storage digits (`storageDigits` in @amboras-dev/money): 0 for JPY/KRW/VND…, 3 for
|
|
252
|
+
* KWD/BHD/OMR/TND/JOD/IQD/LYD, else 2. An unknown code throws `currency_invalid`.
|
|
253
|
+
*/
|
|
254
254
|
export declare function fractionDigits(currency: string): 0 | 2 | 3;
|
|
255
255
|
/**
|
|
256
|
-
* Amboras storage rule: ×1000 for the seven
|
|
257
|
-
* other code INCLUDING zero-decimal ones (¥5 is
|
|
258
|
-
*
|
|
256
|
+
* Amboras storage rule (`storageScale` in @amboras-dev/money): ×1000 for the seven
|
|
257
|
+
* three-decimal codes, ×100 for every other code INCLUDING zero-decimal ones (¥5 is
|
|
258
|
+
* stored as 500). An unknown code throws `currency_invalid`.
|
|
259
259
|
*/
|
|
260
260
|
export declare function storageScale(currency: string): 100 | 1000;
|
|
261
261
|
/**
|
|
262
|
-
* Major → stored minor integer
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
* (exact at any magnitude), or when it is within float noise of such an amount
|
|
269
|
-
* (0.1 + 0.2 → 0.30). Noise is bounded absolutely, so a real extra digit is never
|
|
270
|
-
* rounded away, however large the amount.
|
|
262
|
+
* Major → stored minor integer: `fromMajor(major, currency).amount` from
|
|
263
|
+
* @amboras-dev/money. Throws MoneyError (`invalid_input`) when the amount has more
|
|
264
|
+
* fraction digits than the currency allows (19.999 USD, 5.5 JPY), is not a finite
|
|
265
|
+
* number, or does not fit (2^46 units of the currency's digits). Float noise is
|
|
266
|
+
* accepted (0.1 + 0.2 → 0.30); a real extra digit never is. Pass `field` to name the
|
|
267
|
+
* input field in the error.
|
|
271
268
|
*/
|
|
272
269
|
export declare function toStorageAmount(major: number, currency: string, field?: string): number;
|
|
273
|
-
/**
|
|
270
|
+
/**
|
|
271
|
+
* Stored minor amount → major units: `toMajorNumber(money(minor, currency))` from
|
|
272
|
+
* @amboras-dev/money. The stored amount must be a safe integer.
|
|
273
|
+
*/
|
|
274
274
|
export declare function fromStorageAmount(minor: number, currency: string): number;
|
|
275
275
|
interface MoneyView {
|
|
276
276
|
amount: number;
|
|
@@ -280,9 +280,10 @@ interface MoneyView {
|
|
|
280
280
|
/** Output schema for a MoneyView (what `moneyView` returns), for capability outputs. */
|
|
281
281
|
export declare const moneyViewSchema: z.ZodType<MoneyView>;
|
|
282
282
|
/**
|
|
283
|
-
* A stored amount as the merchant reads it
|
|
284
|
-
*
|
|
285
|
-
*
|
|
283
|
+
* A stored amount as the merchant reads it: `moneyView` from @amboras-dev/money/ai.
|
|
284
|
+
* `amount` is exact; `display` shows the currency's display digits, widened to keep a
|
|
285
|
+
* stored value finer than them (¥5.5 stays visible, HUF 435000 is `HUF 4,350`). An
|
|
286
|
+
* unknown code throws `currency_invalid`.
|
|
286
287
|
*/
|
|
287
288
|
export declare function moneyView(minor: number, currency: string): MoneyView;
|
|
288
289
|
//#endregion
|
|
@@ -310,4 +311,4 @@ export declare function evaluatePolicy(policy: CapabilityPolicy, ctx: Capability
|
|
|
310
311
|
*/
|
|
311
312
|
export declare function confirmationRequired(policy: Pick<CapabilityPolicy, 'confirm'>, records?: number): boolean;
|
|
312
313
|
//#endregion
|
|
313
|
-
export type
|
|
314
|
+
export { type Actor, type AnyCapabilityDefinition, type Area, type CapabilityAgentSpec, type CapabilityCallContext, type CapabilityDefinition, type CapabilityErrorBody, type CapabilityErrorCode, type CapabilityErrorInit, type CapabilityId, type CapabilityManifest, type CapabilityPolicy, type FromZodErrorOptions, type JsonSchema, MONEY_META_KEY, MONEY_UNIT_SENTENCE, type ManifestEntry, type MoneyCurrency, type MoneyOptions, type MoneyView, type PolicyDecision, type PolicyEnforcement, type Role, type Surface };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
|
+
import { currencyCode, fromMajor, money as money$1, storageDigits, storageScale as storageScale$1, toMajorNumber } from "@amboras-dev/money";
|
|
3
|
+
import { MONEY_META_KEY, MONEY_UNIT_SENTENCE, moneyView as moneyView$1 } from "@amboras-dev/money/ai";
|
|
2
4
|
//#region src/canonical-json.ts
|
|
3
5
|
function serialize(value, seen) {
|
|
4
6
|
if (value !== null && typeof value === "object" && typeof value.toJSON === "function") value = value.toJSON();
|
|
@@ -196,38 +198,6 @@ function isRole(value) {
|
|
|
196
198
|
}
|
|
197
199
|
//#endregion
|
|
198
200
|
//#region src/money.ts
|
|
199
|
-
const ZERO_DECIMAL = /* @__PURE__ */ new Set([
|
|
200
|
-
"JPY",
|
|
201
|
-
"KRW",
|
|
202
|
-
"VND",
|
|
203
|
-
"CLP",
|
|
204
|
-
"PYG",
|
|
205
|
-
"XAF",
|
|
206
|
-
"XOF",
|
|
207
|
-
"BIF",
|
|
208
|
-
"DJF",
|
|
209
|
-
"GNF",
|
|
210
|
-
"ISK",
|
|
211
|
-
"KMF",
|
|
212
|
-
"MGA",
|
|
213
|
-
"RWF",
|
|
214
|
-
"UGX",
|
|
215
|
-
"VUV",
|
|
216
|
-
"XPF"
|
|
217
|
-
]);
|
|
218
|
-
const THREE_DECIMAL = /* @__PURE__ */ new Set([
|
|
219
|
-
"KWD",
|
|
220
|
-
"BHD",
|
|
221
|
-
"OMR",
|
|
222
|
-
"TND",
|
|
223
|
-
"JOD",
|
|
224
|
-
"IQD",
|
|
225
|
-
"LYD"
|
|
226
|
-
]);
|
|
227
|
-
/** The one unit sentence every money field carries, for the model and for people. */
|
|
228
|
-
const MONEY_UNIT_SENTENCE = "Amount in normal currency units as the merchant says it (99 means 99.00; 1.5 means 1.50). Never cents or minor units.";
|
|
229
|
-
/** JSON Schema keyword marking a money field. */
|
|
230
|
-
const MONEY_META_KEY = "x-amboras-money";
|
|
231
201
|
/**
|
|
232
202
|
* A bad amount or currency code. It is an `invalid_input` CapabilityError, so an
|
|
233
203
|
* adapter that maps CapabilityError answers 400 with the rule (and the field,
|
|
@@ -289,61 +259,79 @@ function money(opts) {
|
|
|
289
259
|
[MONEY_META_KEY]: marker
|
|
290
260
|
});
|
|
291
261
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
262
|
+
const RULE_FOR_CODE = new Map(Object.entries({
|
|
263
|
+
precision: "money_precision",
|
|
264
|
+
amount_invalid: "money_invalid",
|
|
265
|
+
overflow: "money_invalid",
|
|
266
|
+
parse: "money_invalid",
|
|
267
|
+
rate_invalid: "money_invalid",
|
|
268
|
+
wire_refused: "money_invalid",
|
|
269
|
+
currency_invalid: "currency_invalid",
|
|
270
|
+
currency_missing: "currency_invalid",
|
|
271
|
+
currency_mismatch: "currency_invalid",
|
|
272
|
+
wire_unsupported: "currency_invalid"
|
|
273
|
+
}));
|
|
274
|
+
/** The caller's code as a known currency (`currencyCode` from @amboras-dev/money), or a kit `currency_invalid`. */
|
|
275
|
+
function kitCurrency(currency) {
|
|
276
|
+
try {
|
|
277
|
+
return currencyCode(currency);
|
|
278
|
+
} catch (error) {
|
|
279
|
+
throw toCapabilityMoneyError(error);
|
|
280
|
+
}
|
|
295
281
|
}
|
|
296
|
-
/**
|
|
282
|
+
/**
|
|
283
|
+
* Internal: an error from @amboras-dev/money as the kit's MoneyError, keyed by its `code`
|
|
284
|
+
* (not `instanceof`, so a second copy of the package still maps). Anything else (never
|
|
285
|
+
* expected) is `money_invalid`.
|
|
286
|
+
*/
|
|
287
|
+
function toCapabilityMoneyError(error, field) {
|
|
288
|
+
const code = error?.code;
|
|
289
|
+
const rule = RULE_FOR_CODE.get(code) ?? "money_invalid";
|
|
290
|
+
return new MoneyError(error instanceof Error ? error.message : String(error), rule, field);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Storage digits (`storageDigits` in @amboras-dev/money): 0 for JPY/KRW/VND…, 3 for
|
|
294
|
+
* KWD/BHD/OMR/TND/JOD/IQD/LYD, else 2. An unknown code throws `currency_invalid`.
|
|
295
|
+
*/
|
|
297
296
|
function fractionDigits(currency) {
|
|
298
|
-
|
|
299
|
-
if (ZERO_DECIMAL.has(code)) return 0;
|
|
300
|
-
if (THREE_DECIMAL.has(code)) return 3;
|
|
301
|
-
return 2;
|
|
297
|
+
return storageDigits(kitCurrency(currency));
|
|
302
298
|
}
|
|
303
299
|
/**
|
|
304
|
-
* Amboras storage rule: ×1000 for the seven
|
|
305
|
-
* other code INCLUDING zero-decimal ones (¥5 is
|
|
306
|
-
*
|
|
300
|
+
* Amboras storage rule (`storageScale` in @amboras-dev/money): ×1000 for the seven
|
|
301
|
+
* three-decimal codes, ×100 for every other code INCLUDING zero-decimal ones (¥5 is
|
|
302
|
+
* stored as 500). An unknown code throws `currency_invalid`.
|
|
307
303
|
*/
|
|
308
304
|
function storageScale(currency) {
|
|
309
|
-
return
|
|
310
|
-
}
|
|
311
|
-
const MAX_UNITS = 2 ** 46;
|
|
312
|
-
/** Decimal places in the shortest text form of `n` (what JSON carries): 19.99 → 2, 1e-7 → 7, 1.5e+21 → 0. */
|
|
313
|
-
function decimalPlaces(n) {
|
|
314
|
-
const [mantissa, exponent = "0"] = String(Math.abs(n)).split("e");
|
|
315
|
-
const fraction = mantissa.split(".")[1] ?? "";
|
|
316
|
-
return Math.max(0, fraction.length - Number(exponent));
|
|
305
|
+
return storageScale$1(kitCurrency(currency));
|
|
317
306
|
}
|
|
318
307
|
/**
|
|
319
|
-
* Major → stored minor integer
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
* (exact at any magnitude), or when it is within float noise of such an amount
|
|
326
|
-
* (0.1 + 0.2 → 0.30). Noise is bounded absolutely, so a real extra digit is never
|
|
327
|
-
* rounded away, however large the amount.
|
|
308
|
+
* Major → stored minor integer: `fromMajor(major, currency).amount` from
|
|
309
|
+
* @amboras-dev/money. Throws MoneyError (`invalid_input`) when the amount has more
|
|
310
|
+
* fraction digits than the currency allows (19.999 USD, 5.5 JPY), is not a finite
|
|
311
|
+
* number, or does not fit (2^46 units of the currency's digits). Float noise is
|
|
312
|
+
* accepted (0.1 + 0.2 → 0.30); a real extra digit never is. Pass `field` to name the
|
|
313
|
+
* input field in the error.
|
|
328
314
|
*/
|
|
329
315
|
function toStorageAmount(major, currency, field) {
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
if (!(decimalPlaces(major) <= digits) && noise > Math.min(8 * Number.EPSILON * Math.max(1, Math.abs(inDigits)), 1e-6)) throw new MoneyError(`${major} has more than ${digits} decimal places, the most ${code} allows`, "money_precision", field);
|
|
338
|
-
const stored = whole * (scale / 10 ** digits);
|
|
339
|
-
if (Math.abs(whole) > MAX_UNITS || !Number.isSafeInteger(stored)) throw new MoneyError(`${major} ${code} is too large to store`, "money_invalid", field);
|
|
340
|
-
return stored === 0 ? 0 : stored;
|
|
316
|
+
const code = kitCurrency(currency);
|
|
317
|
+
if (typeof major !== "number") throw new MoneyError(`Amount must be a finite number, got ${String(major)}`, "money_invalid", field);
|
|
318
|
+
try {
|
|
319
|
+
return fromMajor(major, code).amount;
|
|
320
|
+
} catch (error) {
|
|
321
|
+
throw toCapabilityMoneyError(error, field);
|
|
322
|
+
}
|
|
341
323
|
}
|
|
342
|
-
/**
|
|
324
|
+
/**
|
|
325
|
+
* Stored minor amount → major units: `toMajorNumber(money(minor, currency))` from
|
|
326
|
+
* @amboras-dev/money. The stored amount must be a safe integer.
|
|
327
|
+
*/
|
|
343
328
|
function fromStorageAmount(minor, currency) {
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
329
|
+
const code = kitCurrency(currency);
|
|
330
|
+
try {
|
|
331
|
+
return toMajorNumber(money$1(minor, code));
|
|
332
|
+
} catch (error) {
|
|
333
|
+
throw toCapabilityMoneyError(error);
|
|
334
|
+
}
|
|
347
335
|
}
|
|
348
336
|
/** Output schema for a MoneyView (what `moneyView` returns), for capability outputs. */
|
|
349
337
|
const moneyViewSchema = z.object({
|
|
@@ -352,25 +340,18 @@ const moneyViewSchema = z.object({
|
|
|
352
340
|
display: z.string().describe("Formatted for people, e.g. \"$19.99\".")
|
|
353
341
|
});
|
|
354
342
|
/**
|
|
355
|
-
* A stored amount as the merchant reads it
|
|
356
|
-
*
|
|
357
|
-
*
|
|
343
|
+
* A stored amount as the merchant reads it: `moneyView` from @amboras-dev/money/ai.
|
|
344
|
+
* `amount` is exact; `display` shows the currency's display digits, widened to keep a
|
|
345
|
+
* stored value finer than them (¥5.5 stays visible, HUF 435000 is `HUF 4,350`). An
|
|
346
|
+
* unknown code throws `currency_invalid`.
|
|
358
347
|
*/
|
|
359
348
|
function moneyView(minor, currency) {
|
|
360
|
-
const code =
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
currency: code,
|
|
367
|
-
display: new Intl.NumberFormat("en", {
|
|
368
|
-
style: "currency",
|
|
369
|
-
currency: code,
|
|
370
|
-
minimumFractionDigits: digits,
|
|
371
|
-
maximumFractionDigits: Math.max(digits, scaleDigits)
|
|
372
|
-
}).format(amount)
|
|
373
|
-
};
|
|
349
|
+
const code = kitCurrency(currency);
|
|
350
|
+
try {
|
|
351
|
+
return moneyView$1(money$1(minor, code));
|
|
352
|
+
} catch (error) {
|
|
353
|
+
throw toCapabilityMoneyError(error);
|
|
354
|
+
}
|
|
374
355
|
}
|
|
375
356
|
//#endregion
|
|
376
357
|
//#region src/json-schema.ts
|
|
@@ -551,7 +532,7 @@ function checkFieldName(id, name, schema) {
|
|
|
551
532
|
}
|
|
552
533
|
function checkMoneyNode(id, input, node) {
|
|
553
534
|
const description = node.description;
|
|
554
|
-
if (typeof description !== "string" || !description.includes(
|
|
535
|
+
if (typeof description !== "string" || !description.includes(MONEY_UNIT_SENTENCE)) fail(id, "a money() field lost its unit sentence; pass money({ ..., describe }) instead of .describe()/.meta()");
|
|
555
536
|
const marker = node[MONEY_META_KEY];
|
|
556
537
|
const field = isRecord(marker) ? marker.currencyField : void 0;
|
|
557
538
|
if (isRecord(marker) && marker.currency === "store" && field === void 0) return;
|
|
@@ -577,7 +558,7 @@ function checkInputSchema(id, input) {
|
|
|
577
558
|
const keys = finiteKeys(node);
|
|
578
559
|
if (keys) for (const name of keys) checkFieldName(id, name, node.additionalProperties);
|
|
579
560
|
if (node.additionalProperties !== void 0 && node.additionalProperties !== false && !keys || "patternProperties" in node || "propertyNames" in node && !keys) fail(id, "input objects must declare their keys (no z.record with open keys, z.looseObject or .passthrough())");
|
|
580
|
-
if (
|
|
561
|
+
if (MONEY_META_KEY in node) checkMoneyNode(id, input, node);
|
|
581
562
|
});
|
|
582
563
|
}
|
|
583
564
|
function checkHideFields(id, input, hideFields) {
|
package/package.json
CHANGED
|
@@ -1,57 +1,60 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
"name": "@amboras-dev/capability-kit",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Capability contract for Amboras: defineCapability, major-unit money (on @amboras-dev/money), the shared error contract, pure policy evaluation, idempotency helpers and a deterministic manifest. Peer dependency on zod.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Ecomcoder/amboras-core.git",
|
|
9
|
+
"directory": "packages/capability-kit"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "./dist/index.cjs",
|
|
13
|
+
"module": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.cts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"import": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"require": {
|
|
22
|
+
"types": "./dist/index.d.cts",
|
|
23
|
+
"default": "./dist/index.cjs"
|
|
24
|
+
}
|
|
10
25
|
},
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"devDependencies": {
|
|
47
|
-
"@types/node": "22.20.5",
|
|
48
|
-
"@vitest/coverage-v8": "3.2.7",
|
|
49
|
-
"fast-check": "4.3.0",
|
|
50
|
-
"tsdown": "0.23.0",
|
|
51
|
-
"typescript": "5.9.3",
|
|
52
|
-
"vitest": "3.2.7",
|
|
53
|
-
"zod": "4.3.6",
|
|
54
|
-
"zod3": "npm:zod@3.25.76",
|
|
55
|
-
"zod40": "npm:zod@4.0.0"
|
|
56
|
-
}
|
|
57
|
-
}
|
|
26
|
+
"./package.json": "./package.json"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"sideEffects": false,
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=20"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@amboras-dev/money": "0.2.0"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"zod": "^3.25.76 || ^4.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "22.20.5",
|
|
46
|
+
"@vitest/coverage-v8": "3.2.7",
|
|
47
|
+
"fast-check": "4.3.0",
|
|
48
|
+
"tsdown": "0.23.0",
|
|
49
|
+
"typescript": "5.9.3",
|
|
50
|
+
"vitest": "3.2.7",
|
|
51
|
+
"zod": "4.3.6",
|
|
52
|
+
"zod3": "npm:zod@3.25.76",
|
|
53
|
+
"zod40": "npm:zod@4.0.0"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"build": "tsdown",
|
|
57
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json && tsc --noEmit -p tsconfig.zod3.json && tsc --noEmit -p tsconfig.zod40.json",
|
|
58
|
+
"test": "vitest run --coverage && vitest run --config vitest.zod3.config.ts && vitest run --config vitest.zod40.config.ts"
|
|
59
|
+
}
|
|
60
|
+
}
|