Skip to content

Data Type Definitions

Lucid Resourceful provides a comprehensive set of data type classes that define validation, serialization, and OpenAPI schema generation for model properties. These types are based on the OpenAPI 3.0 specification and provide type-safe configuration options for all common data types.

Overview

Data type definitions serve as the foundation for resourceful decorators, providing:

  • Type Validation: Joi schema validation based on OpenAPI 3.0 specifications
  • Schema Generation: Automatic OpenAPI schema generation for API documentation
  • Type Safety: Full TypeScript support with validated configuration options
  • Flexible Construction: Support for both constructor and factory function patterns
  • Common Modifiers: Shared properties like nullable, readOnly, and writeOnly

Common Properties

All resourceful data types extend the base interface and support these common properties:

Base Modifiers

  • nullable: Whether the value can be null (default: false)
  • readOnly: Exclude from create/update operations (default: false)
  • writeOnly: Exclude from response serialization (default: false)
typescript
// Example with common modifiers
const userIdType = ResourcefulUnsignedIntegerType({
  readOnly: true,  // Primary keys are typically read-only
  nullable: false
})

const passwordType = ResourcefulStringType({
  writeOnly: true, // Passwords should not be returned in responses
  minLength: 8,
  maxLength: 128
})

Available Data Types

String Types

String-based data types for text, dates, and binary data:

Numeric Types

Numeric data types with precision and range validation:

Other Types

Additional data types for specific use cases:

Usage Patterns

Constructor vs Factory Function

All data types support both constructor and factory function patterns:

typescript
// Constructor pattern (with new)
const stringType1 = new ResourcefulStringType({ minLength: 1, maxLength: 100 })

// Factory function pattern (without new)
const stringType2 = ResourcefulStringType({ minLength: 1, maxLength: 100 })

// Both create identical instances

Type Validation

Data types validate their configuration options at creation time:

typescript
// Valid configuration
const validType = ResourcefulStringType({
  minLength: 1,
  maxLength: 100,
  pattern: '^[a-zA-Z]+$'
})

// Invalid configuration throws error
try {
  const invalidType = ResourcefulStringType({
    minLength: 100,
    maxLength: 1  // maxLength must be >= minLength
  })
} catch (error) {
  // E_INVALID_RESOURCEFUL_DATA_TYPE_OPTIONS thrown
}

With Decorators

Data types are primarily used with resourceful decorators:

typescript
import { 
  ResourcefulStringType, 
  ResourcefulUnsignedIntegerType,
  ResourcefulBooleanType 
} from '@nhtio/lucid-resourceful/definitions'

class User extends compose(BaseModel, withResourceful({ name: 'User' })) {
  @resourcefulColumn({ 
    isPrimary: true,
    type: ResourcefulUnsignedIntegerType({ readOnly: true })
  })
  declare id: number

  @resourcefulColumn.string({ 
    type: ResourcefulStringType({ minLength: 2, maxLength: 50 }),
    nullable: false
  })
  declare name: string

  @resourcefulColumn.boolean({
    type: ResourcefulBooleanType({ nullable: true })
  })
  declare isActive: boolean
}

Advanced Configuration

Enum Values

String types support enumeration constraints:

typescript
const statusType = ResourcefulStringType({
  minLength: 1,
  maxLength: 20,
  enum: ['draft', 'published', 'archived']
})

Complex Objects

Object types support nested structures with composition patterns:

typescript
const addressType = ResourcefulObjectType({
  properties: {
    street: ResourcefulStringType({ minLength: 1, maxLength: 100 }),
    city: ResourcefulStringType({ minLength: 1, maxLength: 50 }),
    postalCode: ResourcefulStringType({ pattern: '^[0-9]{5}(-[0-9]{4})?$' })
  },
  required: ['street', 'city']
})

Typed Arrays

Array types support complex item validation:

typescript
const tagsType = ResourcefulArrayType({
  items: ResourcefulStringType({ minLength: 1, maxLength: 30 }),
  minItems: 1,
  maxItems: 10,
  uniqueItems: true
})

OpenAPI Integration

All data types automatically generate OpenAPI 3.0 compatible schemas:

typescript
const userSchema = await User.$asOpenApiSchemaObject(ctx, app)
// Generates complete OpenAPI schema object with proper type definitions

Validation Integration

Data types integrate with Joi validation schemas:

typescript
// Each type exposes its Joi schema
const schema = ResourcefulStringType.schema
const validation = schema.validate({ minLength: 1, maxLength: 100 })

Best Practices

  1. Choose appropriate types: Use the most specific type for your data (e.g., ResourcefulDateType for dates rather than generic strings)

  2. Set reasonable constraints: Define appropriate min/max values and lengths to prevent abuse

  3. Use readonly for identifiers: Primary keys and auto-generated fields should be marked as readOnly

  4. Mark sensitive fields: Use writeOnly for passwords and other sensitive data that shouldn't be returned

  5. Validate enums carefully: Use enum constraints for fields with limited valid values

  6. Consider nullability: Explicitly set nullable based on your business logic requirements

  7. Document with examples: Use clear field names and consider adding descriptions for complex types

  8. Test validation: Verify that your type constraints work as expected with real data

API Reference

For complete API documentation of each data type, see:

Next Steps

  • Explore individual data type documentation for detailed configuration options
  • Learn about Decorators to see how types are used in practice
  • Check Validation for advanced validation patterns
  • See OpenAPI for schema generation details