@supacommerce/utils
v0.24.0
Published
Shared utilities for supacommerce — currency helpers, error types, pagination, Result type
Downloads
167
Readme
@supacommerce/utils
Shared utilities for supacommerce. Intentionally public — use these in your own application code.
Installation
pnpm add @supacommerce/utilsCurrency
All monetary values in supacommerce are stored as integers in the smallest currency unit. These helpers handle conversion and formatting.
Zero-decimal currencies (JPY, KRW, VND, etc.) are handled automatically.
import { toMinorUnit, fromMinorUnit, formatCurrency, addMoney, subtractMoney } from "@supacommerce/utils";
toMinorUnit(29.99, "USD"); // 2999
toMinorUnit(100, "JPY"); // 100 (zero-decimal)
fromMinorUnit(2999, "USD"); // 29.99
fromMinorUnit(100, "JPY"); // 100
formatCurrency(2999, "USD"); // "$29.99"
formatCurrency(2999, "USD", "de-DE"); // "29,99 $"
formatCurrency(2999, "GBP"); // "£29.99"
formatCurrency(300, "JPY"); // "¥300"
addMoney(1999, 500); // 2499
subtractMoney(1999, 500); // 1499Result type
A typed alternative to try/catch for operations that can fail predictably.
import { ok, err, isOk, isErr, unwrap, type Result } from "@supacommerce/utils";
function divide(a: number, b: number): Result<number, Error> {
if (b === 0) return err(new Error("Division by zero"));
return ok(a / b);
}
const result = divide(10, 2);
if (isOk(result)) {
console.log(result.value); // 5
}
if (isErr(result)) {
console.error(result.error.message);
}
const value = unwrap(divide(10, 2)); // 5 — throws on errorError types
import {
SupacommerceError,
NotFoundError,
ValidationError,
UnauthorizedError,
ForbiddenError,
ConflictError,
InventoryError,
PaymentError,
} from "@supacommerce/utils";| Class | Status | Code |
| --- | --- | --- |
| NotFoundError | 404 | NOT_FOUND |
| ValidationError | 400 | VALIDATION_ERROR |
| UnauthorizedError | 401 | UNAUTHORIZED |
| ForbiddenError | 403 | FORBIDDEN |
| ConflictError | 409 | CONFLICT |
| InventoryError | 422 | INVENTORY_ERROR |
| PaymentError | 402 | PAYMENT_ERROR |
const e = new NotFoundError("Product", "abc-123");
e.statusCode; // 404
e.code; // "NOT_FOUND"
e.message; // "Product with id 'abc-123' not found"
const ve = new ValidationError("Invalid email", { email: "Must be a valid email" });
ve.fields; // { email: "Must be a valid email" }Pagination
import { buildPaginatedResult, type PaginationParams, type PaginatedResult } from "@supacommerce/utils";
const result = buildPaginatedResult(data, totalCount, { limit: 20, offset: 0 });
// result.data
// result.count
// result.limit
// result.offset
// result.hasMoreID generation
import { generateId } from "@supacommerce/utils";
generateId("cart"); // "cart_a1b2c3d4e5f6g7h8"
generateId("order"); // "order_x9y8z7w6v5u4t3s2"Date helpers
import { nowISO, isPast, isFuture } from "@supacommerce/utils";
nowISO(); // "2024-06-15T12:34:56.789Z"
isPast("2020-01-01T00:00:00Z"); // true
isFuture("2099-01-01T00:00:00Z"); // trueType utilities
import type { RequireKeys, PartialExcept, DeepPartial } from "@supacommerce/utils";
// Make specific keys required
type T = RequireKeys<{ a?: string; b?: string }, "a">;
// { a: string; b?: string }
// Make all keys optional except specified ones
type T = PartialExcept<{ a: string; b: string; c: string }, "a">;
// { a: string; b?: string; c?: string }
// Deep partial
type T = DeepPartial<{ a: { b: string } }>;
// { a?: { b?: string } }License
MIT
