Field Types
Monch provides a field helper with common field types built on Zod. All field types support the full Zod API.
Basic Types
String
field.string() // Required string
field.string().min(1) // At least 1 character
field.string().max(100) // At most 100 characters
field.string().length(10) // Exactly 10 characters
field.string().trim() // Trim whitespace
field.string().toLowerCase() // Convert to lowercase
field.string().optional() // Optional (can be undefined)
field.string().nullable() // Can be null
field.string().default('hello') // Default valueNumber
field.number() // Required number
field.number().int() // Integer only
field.number().positive() // Greater than 0
field.number().negative() // Less than 0
field.number().min(0) // Minimum value
field.number().max(100) // Maximum value
field.number().multipleOf(5) // Must be multiple of 5Boolean
field.boolean() // Required boolean
field.boolean().default(false) // Default valueDate
field.date() // Required date
field.date().min(new Date()) // Minimum date
field.date().max(new Date()) // Maximum date
field.datetime() // Date with default to nowID Types
ObjectId
// Auto-generating ObjectId (for _id field)
field.id()
// Required ObjectId reference (for foreign keys)
field.objectId()Both accept strings and automatically convert them to ObjectId:
await Users.insertOne({
_id: '507f1f77bcf86cd799439011', // Converted to ObjectId
name: 'Alice',
});UUID
field.uuid() // Auto-generating UUID v4
// Result: '123e4567-e89b-12d3-a456-426614174000'Validation Types
Email
field.email() // Email validationURL
field.url() // URL validationEnum
// String enum
field.enum(['pending', 'active', 'suspended'])
// With default
field.enum(['user', 'admin']).default('user')Complex Types
Array
// Array of strings
field.array(field.string())
// Array of numbers with constraints
field.array(field.number()).min(1).max(10)
// Array of objects
field.array(field.object({
name: field.string(),
value: field.number(),
}))Object
// Nested object
field.object({
street: field.string(),
city: field.string(),
zip: field.string(),
country: field.string().default('US'),
})
// Optional nested object
field.object({
bio: field.string().optional(),
website: field.url().optional(),
}).optional()BSON Types
Long (64-bit Integer)
field.long() // MongoDB Long (Int64)
// Usage
await Stats.insertOne({
viewCount: Long.fromNumber(9007199254740993), // Beyond JS safe integer
});Serialization
Long values serialize to number when within JavaScript's safe integer range (±9,007,199,254,740,991). Values outside this range serialize to bigint to preserve precision.
Decimal128 (High-Precision Decimal)
field.decimal() // MongoDB Decimal128
// Usage - great for financial calculations
await Accounts.insertOne({
balance: Decimal128.fromString('99999999999999.99'),
});Binary
field.binary() // MongoDB Binary
// Usage
await Files.insertOne({
content: new Binary(Buffer.from('hello')),
});Timestamp
field.timestamp() // MongoDB Timestamp
// Usage - internal MongoDB operations
await OpLog.insertOne({
ts: new Timestamp({ t: 1234567890, i: 1 }),
});Serialization
Timestamp serializes to { t: number, i: number } where t is the timestamp and i is the increment.
Money Type
Built-in currency support with 30+ currencies, stored as Decimal128 for precision:
field.money() // Default: USD
field.money({ currency: 'EUR' }) // Euro
field.money({ currency: 'JPY' }) // Japanese Yen (no decimals)
field.money({ currency: 'BTC' }) // Bitcoin (8 decimals)Money Options
field.money({
currency: 'USD', // Default currency code (default: 'USD')
min: 0, // Minimum amount
max: 10000, // Maximum amount
allowNegative: false, // Allow negative amounts (default: false)
});MoneyValue Structure
Stored as Decimal128 for financial precision:
{
amount: Decimal128, // High-precision decimal value
currency: string, // Currency code (e.g., 'USD')
}Flexible Input Formats
Money fields accept multiple input formats:
await Products.insertOne({
name: 'Widget',
price: 29.99, // Number
priceEUR: '49.99', // String
priceJPY: { amount: 3500, currency: 'JPY' }, // Object
});
// Stored as Decimal128:
// {
// price: { amount: Decimal128('29.99'), currency: 'USD' },
// priceEUR: { amount: Decimal128('49.99'), currency: 'EUR' },
// priceJPY: { amount: Decimal128('3500'), currency: 'JPY' }
// }Example Usage
import { collection, field, Money } from '@codician-team/monch';
const Products = collection({
name: 'products',
schema: {
_id: field.id(),
name: field.string(),
price: field.money({ currency: 'USD' }),
},
});
// Insert with decimal amount
const product = await Products.insertOne({
name: 'Widget',
price: 19.99,
});
// Use Money utility class for operations
Money.format(product.price); // '$19.99'
Money.toCents(product.price); // 1999 (for Stripe)
Money.toNumber(product.price); // 19.99Supported Currencies
USD, EUR, GBP, JPY, CNY, INR, AUD, CAD, CHF, HKD, SGD, SEK, KRW, NOK, NZD, MXN, TWD, ZAR, BRL, DKK, PLN, THB, ILS, IDR, CZK, AED, TRY, HUF, CLP, SAR, PHP, MYR, COP, RUB, RON, BTC, and ETH.
Money Utility Class
The Money class provides all operations for monetary values:
import { Money } from '@codician-team/monch';
// Formatting
Money.format(price); // '$99.99'
Money.format(price, { precision: 0 }); // '$100'
// Conversions
Money.toNumber(price); // 99.99 (may lose precision)
Money.toString(price); // '99.99' (exact)
Money.toCents(price); // 9999 (for payment APIs)
Money.fromCents(9999, 'USD'); // MoneyValue
// Create MoneyValue
Money.from(99.99); // From number
Money.from('99.99', 'EUR'); // From string
Money.from({ amount: 99.99, currency: 'GBP' }); // From object
// Arithmetic
Money.add(price, tax); // Add two values
Money.subtract(price, discount); // Subtract
Money.multiply(price, 1.1); // Multiply (10% increase)
Money.divide(total, 4); // Divide
Money.percentage(price, 15); // Calculate 15%
Money.round(result); // Round to currency precision
// Aggregation
Money.sum([price1, price2]); // Sum array
Money.min(price1, price2); // Find minimum
Money.max(price1, price2); // Find maximum
// Splitting
Money.split(total, 3); // Split equally [$33.34, $33.33, $33.33]
Money.allocate(total, [2,1,1]); // Split by ratios [$50, $25, $25]
// Comparison
Money.equals(a, b); // Check equality
Money.compare(a, b); // -1 | 0 | 1
Money.greaterThan(a, b); // a > b
Money.lessThan(a, b); // a < b
Money.isZero(price); // Check if zero
Money.isPositive(price); // Check if positive
Money.isNegative(price); // Check if negative
Money.abs(price); // Absolute value
Money.negate(price); // Negate value
// JSON serialization
Money.toJSON(price);
// { amount: '99.99', currency: 'USD', display: '$99.99', cents: 9999 }Currency Configuration
import { getCurrencyConfig, CURRENCY_CONFIGS } from '@codician-team/monch';
// Get currency configuration
const config = getCurrencyConfig('USD');
// { code: 'USD', symbol: '$', precision: 2, symbolPosition: 'before' }
// Access all currency configs
CURRENCY_CONFIGS.EUR // { code: 'EUR', symbol: '€', ... }Quick Reference
| Method | Output Type | Description |
|---|---|---|
field.id() | ObjectId | Auto-generating ObjectId |
field.objectId() | ObjectId | Required ObjectId reference |
field.uuid() | string | Auto-generating UUID |
field.string() | string | String |
field.number() | number | Number |
field.boolean() | boolean | Boolean |
field.date() | Date | Date |
field.datetime() | Date | Date with default to now |
field.email() | string | Email validation |
field.url() | string | URL validation |
field.enum([...]) | union | Enum type |
field.array(type) | T[] | Array of type |
field.object({...}) | object | Nested object |
field.long() | Long | 64-bit integer |
field.decimal() | Decimal128 | High-precision decimal |
field.binary() | Binary | Binary data |
field.timestamp() | Timestamp | MongoDB timestamp |
field.money(opts?) | MoneyValue | Currency with formatting |