Skip to main content

Data Types

Cocobase supports all standard JSON data types plus additional type conversion utilities for strongly-typed applications.

Primitive Types

String

Text data of any length.
{
  "name": "Alice Johnson",
  "bio": "Full-stack developer passionate about clean code",
  "website": "https://alice.dev"
}

Number

Integers and floating-point numbers.
{
  "age": 28,
  "price": 99.99,
  "rating": 4.5,
  "quantity": 100
}
Numbers are stored as IEEE 754 double-precision floating-point. Maximum safe integer: 2^53 - 1 (9,007,199,254,740,991)

Boolean

True or false values.
{
  "isActive": true,
  "emailVerified": false,
  "hasSubscription": true
}

Null

Represents absence of a value.
{
  "middleName": null,
  "avatar": null
}

Complex Types

Object

Nested JSON objects for structured data.
{
  "address": {
    "street": "123 Main St",
    "city": "New York",
    "zipCode": "10001",
    "coordinates": {
      "lat": 40.7128,
      "lng": -74.0060
    }
  }
}
Nesting limit: 100 levels deep

Array

Ordered collections of any type.
{
  "tags": ["javascript", "react", "nodejs"],
  "scores": [85, 92, 78, 95],
  "metadata": [
    { "key": "category", "value": "tech" },
    { "key": "priority", "value": 1 }
  ]
}
Maximum length: 100,000 elements

Date and Time

Dates are stored as ISO 8601 strings.
{
  "createdAt": "2024-01-15T10:30:00Z",
  "publishDate": "2024-02-01T00:00:00Z",
  "lastLogin": "2024-01-20T14:45:30.123Z"
}
// Create with current date
await db.createDocument("events", {
  name: "Product Launch",
  date: new Date().toISOString()
});

// Parse date from document
const event = await db.getDocument("events", "event_123");
const date = new Date(event.date);
console.log(date.toLocaleDateString()); // "1/15/2024"

Type Conversion (Flutter/Dart)

Flutter SDK provides type converters for type-safe operations.

Defining Converters

// models/user.dart
class User {
  final String id;
  final String name;
  final String email;
  final int age;
  final DateTime createdAt;

  User({
    required this.id,
    required this.name,
    required this.email,
    required this.age,
    required this.createdAt,
  });

  // From JSON
  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'] as String,
      name: json['name'] as String,
      email: json['email'] as String,
      age: json['age'] as int,
      createdAt: DateTime.parse(json['createdAt'] as String),
    );
  }

  // To JSON
  Map<String, dynamic> toJson() {
    return {
      'name': name,
      'email': email,
      'age': age,
    };
  }
}

Registering Converters

// Register converters globally
db.registerConverter<User>(
  fromJson: (json) => User.fromJson(json),
  toJson: (user) => user.toJson(),
);

// Use typed operations
final user = await db.createDocument<User>('users', User(
  id: '',
  name: 'Alice',
  email: '[email protected]',
  age: 28,
  createdAt: DateTime.now(),
));

// user is strongly typed
print(user.name); // Alice

TypeScript Type Definitions

Define interfaces for compile-time type safety:
interface Product {
  id: string;
  name: string;
  description: string;
  price: number;
  inStock: boolean;
  tags: string[];
  category: "electronics" | "clothing" | "books";
  metadata: {
    brand: string;
    sku: string;
  };
  createdAt: string;
  updatedAt: string;
}

// Type-safe operations
const product = await db.createDocument<Product>("products", {
  name: "Laptop",
  description: "High-performance laptop",
  price: 1299.99,
  inStock: true,
  tags: ["computer", "electronics"],
  category: "electronics",
  metadata: {
    brand: "TechCorp",
    sku: "LAP-001",
  },
});

// TypeScript knows the shape
console.log(product.price); // ✅ number
console.log(product.foo); // ❌ Error: Property 'foo' does not exist

Special Data Types

File References

Store file URLs or references to uploaded files:
{
  "profilePicture": "https://storage.cocobase.buzz/files/avatar.jpg",
  "documents": [
    "https://storage.cocobase.buzz/files/resume.pdf",
    "https://storage.cocobase.buzz/files/portfolio.pdf"
  ]
}
See File Storage for details.

Document References

Store references to other documents:
{
  "userId": "user_123",           // Reference to user document
  "categoryId": "category_456",   // Reference to category document
  "relatedPosts": [               // Array of references
    "post_789",
    "post_012"
  ]
}
Use population to fetch referenced documents.

Geolocation

Store coordinates as nested objects:
{
  "location": {
    "lat": 40.7128,
    "lng": -74.0060,
    "accuracy": 10
  }
}
Query with range filters:
const nearbyPlaces = await db.listDocuments("places", {
  filters: {
    "location.lat": { $gte: 40.0, $lte: 41.0 },
    "location.lng": { $gte: -75.0, $lte: -73.0 },
  },
});

Type Validation

While Cocobase is schema-less, you can implement validation in your application:

Using Zod

import { z } from "zod";

const UserSchema = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().min(0).max(150),
  role: z.enum(["admin", "user", "moderator"]),
});

// Validate before creating
const userData = {
  name: "Alice",
  email: "[email protected]",
  age: 28,
  role: "user" as const,
};

const validatedData = UserSchema.parse(userData);
await db.createDocument("users", validatedData);

Type Coercion

Cocobase automatically handles some type conversions:
// Numbers
"42"42         // String to number in numeric context
42.042         // Float to int when whole number

// Booleans
"true"true     // String to boolean
1true          // Number to boolean
0false

// Dates
"2024-01-15""2024-01-15T00:00:00Z"  // Date string normalization
Automatic coercion is not guaranteed. Always store data in the correct type to avoid unexpected behavior.

Best Practices

Keep field types consistent across documents:
// ✅ Good - Consistent types
{ "price": 99.99 }
{ "price": 149.99 }

// ❌ Bad - Mixed types
{ "price": 99.99 }
{ "price": "149.99" }  // String instead of number
Always use ISO 8601 format for dates:
// ✅ Good
{ "date": "2024-01-15T10:30:00Z" }

// ❌ Bad
{ "date": "01/15/2024" }        // Non-standard format
{ "date": 1705319400000 }       // Unix timestamp
Use arrays when order matters, objects when it doesn’t:
// ✅ Array for ordered list
{
  "steps": ["Mix", "Bake", "Cool", "Serve"]
}

// ✅ Object for key-value pairs
{
  "settings": {
    "theme": "dark",
    "language": "en",
    "notifications": true
  }
}
Always define interfaces for your data models:
// ✅ Good - Clear interface
interface Post {
  id: string;
  title: string;
  content: string;
  authorId: string;
  tags: string[];
  publishedAt: string;
}

// Use in operations
const post = await db.createDocument<Post>("posts", {...});

Type Limits

TypeMaximum Size/Length
String16 MB per document
Number±1.7976931348623157 × 10^308
Array100,000 elements
Object100 levels of nesting
Document16 MB total size

Next Steps