Skip to main content

Field Types & Options

Fields define the properties of your entities. Each field has a type and optional configuration.

Field Types​

String Types​

string​

Basic text field.

{
"title": {
"type": "string",
"required": true
}
}

url​

URL with validation.

{
"website": {
"type": "url",
"optional": true
}
}

Numeric Types​

int​

Integer number.

{
"count": {
"type": "int",
"default": 0
}
}

float​

Floating point number.

{
"rating": {
"type": "float",
"optional": true
}
}

Boolean​

{
"isActive": {
"type": "boolean",
"default": true
}
}

Date & Time​

isoDate​

ISO 8601 date string.

{
"dueDate": {
"type": "isoDate",
"optional": true
}
}

Object ID​

objectId​

MongoDB ObjectId reference.

{
"authorId": {
"type": "objectId",
"ref": "User",
"required": true
}
}

Enums​

Define a set of allowed values.

Simple format:

{
"status": {
"type": "enum",
"values": ["draft", "published", "archived"],
"default": "draft"
}
}

Enhanced format with labels:

{
"priority": {
"type": "enum",
"values": [
{ "key": "low", "label": "Low Priority" },
{ "key": "medium", "label": "Medium Priority" },
{ "key": "high", "label": "High Priority" }
],
"default": "medium"
}
}

Arrays​

String Array​

{
"tags": {
"type": "string[]",
"default": []
}
}

ObjectId Array​

{
"memberIds": {
"type": "objectId[]",
"ref": "User",
"default": []
}
}

Integer Array​

{
"scores": {
"type": "int[]",
"default": []
}
}

Float Array​

{
"prices": {
"type": "float[]",
"default": []
}
}

Boolean Array​

{
"flags": {
"type": "boolean[]",
"default": []
}
}

URL Array​

{
"imageUrls": {
"type": "url[]",
"default": []
}
}

Generic Array​

{
"items": {
"type": "array",
"items": {
"type": "string"
},
"default": []
}
}

Objects​

object​

Free-form object.

{
"metadata": {
"type": "object",
"optional": true
}
}

any​

Any type (no validation).

{
"data": {
"type": "any",
"optional": true
}
}

Field Options​

required / optional​

{
"email": {
"type": "string",
"required": true
},
"bio": {
"type": "string",
"optional": true
}
}

default​

Default value when not provided.

{
"status": {
"type": "enum",
"values": ["active", "inactive"],
"default": "active"
}
}

label​

Human-readable label for UI.

{
"createdAt": {
"type": "isoDate",
"label": "Creation Date"
}
}

ref​

Reference to another entity (for objectId fields).

{
"projectId": {
"type": "objectId",
"ref": "Project",
"required": true
}
}

expose​

Control field visibility across surfaces.

{
"passwordHash": {
"type": "string",
"internal": true,
"expose": {
"contracts": false,
"create": false,
"update": false,
"read": false
}
}
}

Surfaces:

  • contracts - Zod schema
  • create - Create operations
  • update - Update operations
  • read - Read operations

internal​

Mark field as internal (hidden by default, requires explicit expose).

{
"secretKey": {
"type": "string",
"internal": true,
"expose": {
"create": true
}
}
}

select​

Control MongoDB selection (default: true).

{
"largeField": {
"type": "string",
"select": false
}
}

Include field in text search.

{
"title": {
"type": "string",
"search": true
}
}

trackChanges​

Enable field-level change tracking.

{
"approvalStatus": {
"type": "enum",
"values": ["pending", "approved", "rejected"],
"trackChanges": true
}
}

allowedMacros​

Define allowed macro values for default field population. These are schema-recognized macros used in production blueprints:

{
"requestId": {
"type": "string",
"allowedMacros": ["UUID"]
}
}

Available macros:

MacroDescription
UUIDGenerate a new UUID v4
NOWCurrent ISO date-time
TIMESTAMPCurrent Unix timestamp
TODAYCurrent date (YYYY-MM-DD)
USER_IDThe authenticated user's ID

access​

Restrict field-level read and/or write access to specific roles. When defined, the service layer's getFieldsWithAccess() method enforces these restrictions.

{
"costPrice": {
"type": "float",
"access": { "read": ["ADMIN", "MANAGER"] }
},
"internalNotes": {
"type": "string",
"access": {
"read": ["ADMIN"],
"write": ["ADMIN"]
}
}
}

Fields with access.read restrictions are stripped from responses for users whose roles are not in the allowed list. Fields with access.write restrictions are ignored in create/update operations for unauthorized roles.

Special Field Types​

secretKey — One-Way Hash (Write-Only)​

For passwords, API tokens, and secrets you never need to read back. The original value is bcrypt hashed and the plaintext is deleted — it can never be retrieved, only verified.

{
"apiToken": {
"type": "secretKey",
"lastChars": 4
}
}

What the service does on create/update:

  1. Hashes the value with bcrypt → stores as apiTokenHash
  2. Saves the last N characters → stores as apiTokenLastChars (for display like ••••a1b2)
  3. Deletes the original plaintext value

Storage in MongoDB:

{
"apiTokenHash": "$2b$10$rKjLv...",
"apiTokenLastChars": "a1b2"
}

Verification: Use bcrypt.compare(inputValue, storedHash) to verify. The service does not expose a verify method — implement in your route handler.

Options:

PropertyDefaultDescription
lastChars4Number of trailing chars to store for display (0 to disable)

encryptedKey — Two-Way AES-256 Encryption (Read/Write)​

For API keys, webhook secrets, OAuth tokens, and credentials you need to retrieve for making API calls to external services.

{
"webhookSecret": {
"type": "encryptedKey",
"lastChars": 4
}
}

What the service does on create/update:

  1. Encrypts with AES-256-CBC → stores as webhookSecretEncrypted
  2. Saves the last N characters → stores as webhookSecretLastChars
  3. Deletes the original plaintext value

Storage in MongoDB:

{
"webhookSecretEncrypted": "a1b2c3d4e5f6:encrypted_hex_data",
"webhookSecretLastChars": "x9y0"
}

Retrieving the original value:

const decrypted = await service.getDecryptedKey(entityId, 'webhookSecret');

Encryption key: Set RADISH_ENCRYPTION_KEY in your .env. The default is a placeholder — must be changed in production.

Options:

PropertyDefaultDescription
lastChars4Number of trailing chars to store for display (0 to disable)

When to Use Which​

Use CaseTypeWhy
User passwordssecretKeyNever need the original back, verify with bcrypt
API tokens (verification only)secretKeyJust compare hashes
Third-party API keysencryptedKeyNeed to send to external APIs
Webhook signing secretsencryptedKeyNeed to compute HMAC signatures
OAuth access/refresh tokensencryptedKeyNeed to make API calls
Database connection stringsencryptedKeyNeed to connect at runtime

Security Notes​

  • Both field types are excluded from default select queries — they don't appear in list() or get() responses
  • The getDecryptedKey() method requires authentication (service-level access control applies)
  • In production, use a proper key management system (AWS KMS, HashiCorp Vault) and set RADISH_ENCRYPTION_KEY to a secure 32-byte value
  • The lastChars display field is stored in plaintext — set to 0 for maximum security

Settings Field-Level Encryption​

The encryptedKey type also works on individual fields within Setting values via the fieldSchema property. This lets you store complex configuration objects where only sensitive fields are encrypted:

await settingService.set('stripe-config', {
publishableKey: 'pk_live_abc123',
secretKey: 'sk_live_xyz789',
webhookSecret: 'whsec_abc'
}, {
dataType: 'object',
fieldSchema: {
publishableKey: 'string',
secretKey: 'encryptedKey',
webhookSecret: 'encryptedKey'
}
});

Non-sensitive fields stay readable; encrypted fields use the same AES-256-CBC algorithm and RADISH_ENCRYPTION_KEY. See Settings & Encryption for full documentation.

Example Entity with Various Field Types​

{
"entities": {
"Product": {
"fields": {
"name": {
"type": "string",
"required": true,
"label": "Product Name",
"search": true
},
"sku": {
"type": "string",
"required": true,
"label": "SKU"
},
"price": {
"type": "float",
"required": true,
"label": "Price"
},
"stock": {
"type": "int",
"default": 0,
"label": "Stock Count"
},
"category": {
"type": "enum",
"values": ["electronics", "clothing", "food", "other"],
"default": "other",
"label": "Category"
},
"vendorId": {
"type": "objectId",
"ref": "Vendor",
"optional": true,
"label": "Vendor"
},
"tags": {
"type": "string[]",
"default": [],
"label": "Tags"
},
"imageUrls": {
"type": "string[]",
"default": [],
"label": "Product Images"
},
"releaseDate": {
"type": "isoDate",
"optional": true,
"label": "Release Date"
},
"specs": {
"type": "object",
"optional": true,
"label": "Specifications"
},
"isActive": {
"type": "boolean",
"default": true,
"label": "Active Status"
}
}
}
}
}

Next Steps​