Cretex

ocx

The ocx function is a utility for combining different types of values into a single object. This function is very useful for building dynamic configurations or other properties by simplifying flexible management based on runtime conditions. It accepts various input types, such as objects, arrays, functions, or primitive values, and returns an object that combines all relevant properties.

Syntax

function ocx<T extends ocxKey>(...obj: ocxObj<T>[]): ocxAcc<T>;

How ocx works:

  1. Input Processing:

    • Sequentially checks each parameter.
    • If the input is a function, it calls the function and processes the result recursively.
    • If the input is an array, it processes each element recursively.
    • If the input is an object, its properties are merged into the final result.
  2. Output:

    • Primitive values (e.g., strings, numbers, null) are ignored.
    • The final result is an object containing all valid properties from the inputs.
  3. Overwriting Behavior:

    • Duplicate keys are overwritten by the last input in the list.
  4. Falsy Value Filtering (Default ocx() Behavior):

    • Automatically removes keys with falsy values (false, undefined, null, NaN).
  5. Retaining Falsy Values (ocx.raw()):

    • If you need to keep falsy values while merging, use ocx.raw().

Example Usage

ocx(
  { a: 1 },
  [{ b: 2 }, { d: 4, e: null }, { f: undefined, g: NaN }],
  () => ({ c: 3 }),
  key => key?.a && { "key?.a": key.a === 1 },
  {},
  0, // will be ignored
  "string", // will be ignored
  null, // will be ignored
  NaN // will be ignored
);
// { a: 1, b: 2, d: 4, c: 3, 'key?.a': true }

Merging Objects

  • Default behavior
const result = ocx({ name: "John", age: null }, { age: 30, city: "New York" }, () => ({ country: "USA" }));
console.log(result);
// { name: "John", age: 30, city: "New York", country: "USA" }
const dynamic = (prev: ocxKey) => prev?.a && { e: prev.a + 5 };
const result = ocx([{ a: 1 }], [{ b: 2 }, { c: 3 }], { d: 4 }, dynamic);
console.log(result); // { a: 1, b: 2, c: 3, d: 4, e: 6 }
  • Chaining Methods

    • .raw()
      A version of ocx that performs deep merging without removing falsy values.
    const result = ocx.raw({ enabled: false, features: { darkMode: true } }, { features: { darkMode: null, betaMode: true } });
     
    console.log(result);
    // { enabled: false, features: { darkMode: null, betaMode: true } }
    • .preserve()
      A version of ocx that performs a deep join without overwriting the value at the first key, only change the value if it does not exist and without removing falsy values.
    const obj1 = { key1: { nestedKey1: { subKey: "value1", subKey3: false } } };
    const objFn = () => ({ key1: { nestedKey1: { subKey: "newValue1", subKey2: "value2", subKey3: "value3" } } });
     
    const result = ocx.preserve(obj1, objFn);
    console.log(result);
    // {
    //   key1: {
    //     nestedKey1: { subKey: 'value1', subKey3: false, subKey2: 'value2' }
    //   }
    // }

Real-World Examples

Dynamic API Response Combination

const userBase = () => ({
  id: 123,
  name: "Alice",
  email: "alice@example.com",
  settings: { theme: "light", notifications: true }
});
 
const userOverride = {
  email: null, // This will be removed in ocx()
  settings: { notifications: false }
};
 
const response = ocx(userBase, userOverride);
 
console.log(response);
// { id: 123, name: 'Alice', settings: { theme: 'light' } }

Complex API Response Combination with additional data

const user = {
  id: "1ab2C3",
  username: "johndoe92",
  email: "johndoe@example.com",
  role: "admin",
  colors: "red-navy",
  profile: {
    age: 32,
    name: { first: "Johnathan", last: "Doe" },
    gender: "male",
    phone: "+1-555-987-6543",
    avatar: "https://example.com/avatars/johndoe99.png",
    bio: "Software engineer and technology enthusiast who loves coding and open-source projects.",
    education: [
      {
        degree: "BSc Computer Science",
        institution: "MIT",
        yearGraduated: 2014
      },
      {
        degree: "MSc Artificial Intelligence",
        institution: "Stanford University",
        yearGraduated: 2016
      }
    ],
    workExperience: [
      {
        company: "Google",
        role: "Software Engineer",
        startDate: "2016-07-01",
        endDate: "2019-06-30"
      },
      {
        company: "OpenAI",
        role: "Lead Developer",
        startDate: "2019-07-01",
        endDate: "Present"
      }
    ],
    skills: ["JavaScript", "TypeScript", "React", "Next.js", "Node.js", "AI", "Machine Learning"]
  },
  address: {
    street: "1234 Elm Street",
    city: "Los Angeles",
    state: "California",
    country: "USA",
    zipCode: "90001",
    geo: { lat: 34.0522, lng: -118.2437 }
  },
  socialLink: {
    twitter: "@johndoe",
    linkedIn: "https://linkedin.com/in/johndoe",
    github: "https://github.com/johndoe"
  },
  status: "verified",
  createdAt: "2022-12-15T08:45:00Z",
  lastLogin: "2025-01-30T14:32:00Z",
  lastIp: "192.168.1.100",
  twoFactorAuth: {
    enabled: true,
    methods: ["authenticator_app", "sms", "whatsapp", "email"],
    lastUpdated: "2024-09-20T13:15:00Z"
  },
  activityHistory: [
    {
      action: "login",
      timestamp: "2025-01-30T14:32:00Z",
      device: "iPhone 15 Plus",
      ip: "192.168.1.10"
    },
    {
      action: "update_profile",
      timestamp: "2025-01-28T10:12:00Z",
      changes: ["email", "phone"]
    },
    {
      action: "reset_password",
      timestamp: "2025-01-20T18:45:00Z",
      method: "email_link"
    }
  ],
  securityAlerts: [
    {
      event: "suspicious_login",
      timestamp: "2025-01-15T22:45:00Z",
      location: "Russia",
      status: "blocked"
    },
    {
      event: "password_reset_request",
      timestamp: "2025-01-20T10:00:00Z",
      method: "email",
      status: "approved"
    }
  ],
  notifications: {
    email: true,
    push: true,
    sms: false,
    newsletter: false,
    weeklyReport: true,
    productUpdates: false,
    appUpdates: true,
    securityAlerts: true
  },
  sessions: {
    web: {
      active: true,
      lastLogin: "2025-01-30T14:32:00Z",
      ip: "192.168.1.100"
    },
    windowsApp: { active: false, lastLogin: "2024-12-15T08:45:00Z" },
    mobileApp: {
      active: true,
      lastLogin: "2025-01-28T11:12:00Z",
      device: "iPhone 15 Plus"
    }
  },
  organizations: [
    {
      id: "org-001",
      name: "Tech Innovators Inc.",
      role: "Lead Developer",
      joinedAt: "2023-03-01T09:00:00Z"
    }
  ],
  affiliations: [
    {
      id: "aff-001",
      name: "Open Source Community",
      role: "Contributor",
      since: "2021-06-10T12:00:00Z"
    }
  ],
  enterprises: [
    {
      id: "ent-001",
      name: "Global Tech Solutions",
      role: "Consultant",
      since: "2022-01-15T08:00:00Z"
    }
  ],
  replies: [
    {
      id: "reply-001",
      content: "I totally agree with this!",
      timestamp: "2025-01-29T14:20:00Z"
    }
  ],
  historyLog: [
    {
      action: "profile_update",
      timestamp: "2025-01-28T10:12:00Z",
      details: ["email", "phone"]
    }
  ],
  securityLog: [
    {
      event: "failed_login_attempt",
      timestamp: "2025-01-29T18:00:00Z",
      ip: "192.168.1.50"
    }
  ]
};
 
const preferences = {
  theme: "dark",
  lang: "en-US",
  timezone: "America/Los_Angeles",
  dateFormat: "MM/DD/YYYY",
  timeFormat: "12h",
  accessibility: {
    textSize: "medium",
    contrastMode: "high",
    voiceAssistance: false,
    textToSpeech: true,
    dyslexiaFont: false,
    keyboardNavigation: true
  },
  integrations: {
    googleDrive: { enabled: true, lastSync: "2025-01-15T09:00:00Z" },
    dropbox: { enabled: false },
    slack: { enabled: true, lastSync: "2025-01-10T12:30:00Z" }
  },
  shortcuts: [
    { key: "ctrl + k", action: "Open search bar" },
    { key: "ctrl + n", action: "Create new document" },
    { key: "ctrl + s", action: "Save current work" }
  ]
};
 
const metadata = {
  createdAt: "2023-01-01T10:00:00Z",
  latestUpdated: "2025-01-01T12:45:00Z",
  isActive: false,
  isPremium: true,
  accountType: "business",
  subscription: {
    plan: "Pro",
    startedAt: "2023-02-15T09:00:00Z",
    expiresAt: "2026-02-15T09:00:00Z",
    autoRenew: true,
    paymentMethod: "credit_card",
    lastPaymentDate: "2025-02-01T08:30:00Z",
    invoices: [
      { id: "INV-001", date: "2024-01-15", amount: 299.99, status: "Paid" },
      { id: "INV-002", date: "2025-01-15", amount: 299.99, status: "Pending" }
    ],
    usageStats: {
      storageUsed: "150GB",
      apiCalls: 12500,
      lastBillingCycle: "2025-01-01T00:00:00Z"
    }
  },
  security: {
    lastPasswordChange: "2024-10-10T10:10:00Z",
    failedLoginAttempts: 2,
    passwordStrength: "strong",
    recovery: {
      email: "recovery@example.com",
      phone: "+1-202-555-0199",
      whatsapp: "+1-202-555-0199",
      securityQuestions: [
        {
          question: "What’s your mother’s maiden name?",
          answerHash: "a7b8c9d10e"
        },
        {
          question: "What was your first pet’s name?",
          answerHash: "f2g3h4i5j6"
        }
      ]
    }
  },
  devices: [
    {
      merk: "iPhone 15 Plus",
      brand: "apple",
      model: "A2896",
      os: "iOS 17.2",
      method: "qrcode",
      registeredAt: "2024-12-15T08:30:00Z",
      ipAddress: "192.168.1.12",
      location: {
        country: "USA",
        city: "Los Angeles",
        geo: { lat: 34.0522, lng: -118.2437 }
      },
      lastActive: "2025-01-29T22:15:00Z",
      status: "trusted"
    },
    {
      merk: "ASUS ROG Phone 8",
      brand: "android",
      model: "ZS675KS",
      os: "Android 14",
      method: "passkey",
      registeredAt: "2023-11-20T16:20:00Z",
      ipAddress: "172.16.254.3",
      location: {
        country: "USA",
        city: "San Francisco",
        geo: { lat: 37.7749, lng: -122.4194 }
      },
      lastActive: "2025-01-25T18:05:00Z",
      status: "pending_review"
    },
    {
      merk: 'MacBook Pro 16"',
      brand: "apple",
      model: "M3 Max",
      os: "macOS Sonoma",
      method: "password",
      registeredAt: "2023-09-10T14:10:00Z",
      ipAddress: "192.168.1.20",
      location: {
        country: "USA",
        city: "New York",
        geo: { lat: 40.7128, lng: -74.006 }
      },
      lastActive: "2025-01-30T09:15:00Z",
      status: "trusted"
    }
  ],
  accessedApps: [
    { name: "VS Code", lastUsed: "2025-01-29T22:10:00Z" },
    { name: "GitHub", lastUsed: "2025-01-30T09:00:00Z" },
    { name: "Slack", lastUsed: "2025-01-28T15:45:00Z" }
  ]
};
 
const updated = {
  notifications: {
    email: {
      enabled: true,
      frequency: "daily",
      categories: ["security", "updates"]
    },
    push: {
      enabled: true,
      frequency: "instant",
      categories: ["messages", "reminders"]
    },
    sms: { enabled: false, reason: "User preference" },
    newsletter: { enabled: false },
    weeklyReport: { enabled: true, lastSent: "2025-01-29T10:00:00Z" }
  },
  colors: {
    dark: "shane",
    light: "salmon",
    accent: "goldenrod",
    background: "#121212",
    text: "#FFFFFF"
  }
};
 
const apiResponse = ocx(
  user,
  updated,
  { preferences, metadata },
  key => ({
    fullName: [key?.profile?.name?.first, key?.profile?.name?.last].join(" ").trim(),
    timestamp: new Date().toISOString()
  }),
  key => key?.role === "admin" && { permissions: ["read", "write", "delete"] }
);
 
console.log(JSON.stringify(apiResponse, (_, value) => value, 2));
  • Result:
    {
      "id": "1ab2C3",
      "username": "johndoe92",
      "email": "johndoe@example.com",
      "role": "admin",
      "colors": {
        "dark": "shane",
        "light": "salmon",
        "accent": "goldenrod",
        "background": "#121212",
        "text": "#FFFFFF"
      },
      "profile": {
        "age": 32,
        "name": {
          "first": "Johnathan",
          "last": "Doe"
        },
        "gender": "male",
        "phone": "+1-555-987-6543",
        "avatar": "https://example.com/avatars/johndoe99.png",
        "bio": "Software engineer and technology enthusiast who loves coding and open-source projects.",
        "education": [
          {
            "degree": "BSc Computer Science",
            "institution": "MIT",
            "yearGraduated": 2014
          },
          {
            "degree": "MSc Artificial Intelligence",
            "institution": "Stanford University",
            "yearGraduated": 2016
          }
        ],
        "workExperience": [
          {
            "company": "Google",
            "role": "Software Engineer",
            "startDate": "2016-07-01",
            "endDate": "2019-06-30"
          },
          {
            "company": "OpenAI",
            "role": "Lead Developer",
            "startDate": "2019-07-01",
            "endDate": "Present"
          }
        ],
        "skills": ["JavaScript", "TypeScript", "React", "Next.js", "Node.js", "AI", "Machine Learning"]
      },
      "address": {
        "street": "1234 Elm Street",
        "city": "Los Angeles",
        "state": "California",
        "country": "USA",
        "zipCode": "90001",
        "geo": {
          "lat": 34.0522,
          "lng": -118.2437
        }
      },
      "socialLink": {
        "twitter": "@johndoe",
        "linkedIn": "https://linkedin.com/in/johndoe",
        "github": "https://github.com/johndoe"
      },
      "status": "verified",
      "createdAt": "2022-12-15T08:45:00Z",
      "lastLogin": "2025-01-30T14:32:00Z",
      "lastIp": "192.168.1.100",
      "twoFactorAuth": {
        "enabled": true,
        "methods": ["authenticator_app", "sms", "whatsapp", "email"],
        "lastUpdated": "2024-09-20T13:15:00Z"
      },
      "activityHistory": [
        {
          "action": "login",
          "timestamp": "2025-01-30T14:32:00Z",
          "device": "iPhone 15 Plus",
          "ip": "192.168.1.10"
        },
        {
          "action": "update_profile",
          "timestamp": "2025-01-28T10:12:00Z",
          "changes": ["email", "phone"]
        },
        {
          "action": "reset_password",
          "timestamp": "2025-01-20T18:45:00Z",
          "method": "email_link"
        }
      ],
      "securityAlerts": [
        {
          "event": "suspicious_login",
          "timestamp": "2025-01-15T22:45:00Z",
          "location": "Russia",
          "status": "blocked"
        },
        {
          "event": "password_reset_request",
          "timestamp": "2025-01-20T10:00:00Z",
          "method": "email",
          "status": "approved"
        }
      ],
      "notifications": {
        "email": {
          "enabled": true,
          "frequency": "daily",
          "categories": ["security", "updates"]
        },
        "push": {
          "enabled": true,
          "frequency": "instant",
          "categories": ["messages", "reminders"]
        },
        "sms": {
          "reason": "User preference"
        },
        "weeklyReport": {
          "enabled": true,
          "lastSent": "2025-01-29T10:00:00Z"
        },
        "appUpdates": true,
        "securityAlerts": true
      },
      "sessions": {
        "web": {
          "active": true,
          "lastLogin": "2025-01-30T14:32:00Z",
          "ip": "192.168.1.100"
        },
        "windowsApp": {
          "lastLogin": "2024-12-15T08:45:00Z"
        },
        "mobileApp": {
          "active": true,
          "lastLogin": "2025-01-28T11:12:00Z",
          "device": "iPhone 15 Plus"
        }
      },
      "organizations": [
        {
          "id": "org-001",
          "name": "Tech Innovators Inc.",
          "role": "Lead Developer",
          "joinedAt": "2023-03-01T09:00:00Z"
        }
      ],
      "affiliations": [
        {
          "id": "aff-001",
          "name": "Open Source Community",
          "role": "Contributor",
          "since": "2021-06-10T12:00:00Z"
        }
      ],
      "enterprises": [
        {
          "id": "ent-001",
          "name": "Global Tech Solutions",
          "role": "Consultant",
          "since": "2022-01-15T08:00:00Z"
        }
      ],
      "replies": [
        {
          "id": "reply-001",
          "content": "I totally agree with this!",
          "timestamp": "2025-01-29T14:20:00Z"
        }
      ],
      "historyLog": [
        {
          "action": "profile_update",
          "timestamp": "2025-01-28T10:12:00Z",
          "details": ["email", "phone"]
        }
      ],
      "securityLog": [
        {
          "event": "failed_login_attempt",
          "timestamp": "2025-01-29T18:00:00Z",
          "ip": "192.168.1.50"
        }
      ],
      "preferences": {
        "theme": "dark",
        "lang": "en-US",
        "timezone": "America/Los_Angeles",
        "dateFormat": "MM/DD/YYYY",
        "timeFormat": "12h",
        "accessibility": {
          "textSize": "medium",
          "contrastMode": "high",
          "textToSpeech": true,
          "keyboardNavigation": true
        },
        "integrations": {
          "googleDrive": {
            "enabled": true,
            "lastSync": "2025-01-15T09:00:00Z"
          },
          "slack": {
            "enabled": true,
            "lastSync": "2025-01-10T12:30:00Z"
          }
        },
        "shortcuts": [
          {
            "key": "ctrl + k",
            "action": "Open search bar"
          },
          {
            "key": "ctrl + n",
            "action": "Create new document"
          },
          {
            "key": "ctrl + s",
            "action": "Save current work"
          }
        ]
      },
      "metadata": {
        "createdAt": "2023-01-01T10:00:00Z",
        "latestUpdated": "2025-01-01T12:45:00Z",
        "isPremium": true,
        "accountType": "business",
        "subscription": {
          "plan": "Pro",
          "startedAt": "2023-02-15T09:00:00Z",
          "expiresAt": "2026-02-15T09:00:00Z",
          "autoRenew": true,
          "paymentMethod": "credit_card",
          "lastPaymentDate": "2025-02-01T08:30:00Z",
          "invoices": [
            {
              "id": "INV-001",
              "date": "2024-01-15",
              "amount": 299.99,
              "status": "Paid"
            },
            {
              "id": "INV-002",
              "date": "2025-01-15",
              "amount": 299.99,
              "status": "Pending"
            }
          ],
          "usageStats": {
            "storageUsed": "150GB",
            "apiCalls": 12500,
            "lastBillingCycle": "2025-01-01T00:00:00Z"
          }
        },
        "security": {
          "lastPasswordChange": "2024-10-10T10:10:00Z",
          "failedLoginAttempts": 2,
          "passwordStrength": "strong",
          "recovery": {
            "email": "recovery@example.com",
            "phone": "+1-202-555-0199",
            "whatsapp": "+1-202-555-0199",
            "securityQuestions": [
              {
                "question": "What’s your mother’s maiden name?",
                "answerHash": "a7b8c9d10e"
              },
              {
                "question": "What was your first pet’s name?",
                "answerHash": "f2g3h4i5j6"
              }
            ]
          }
        },
        "devices": [
          {
            "merk": "iPhone 15 Plus",
            "brand": "apple",
            "model": "A2896",
            "os": "iOS 17.2",
            "method": "qrcode",
            "registeredAt": "2024-12-15T08:30:00Z",
            "ipAddress": "192.168.1.12",
            "location": {
              "country": "USA",
              "city": "Los Angeles",
              "geo": {
                "lat": 34.0522,
                "lng": -118.2437
              }
            },
            "lastActive": "2025-01-29T22:15:00Z",
            "status": "trusted"
          },
          {
            "merk": "ASUS ROG Phone 8",
            "brand": "android",
            "model": "ZS675KS",
            "os": "Android 14",
            "method": "passkey",
            "registeredAt": "2023-11-20T16:20:00Z",
            "ipAddress": "172.16.254.3",
            "location": {
              "country": "USA",
              "city": "San Francisco",
              "geo": {
                "lat": 37.7749,
                "lng": -122.4194
              }
            },
            "lastActive": "2025-01-25T18:05:00Z",
            "status": "pending_review"
          },
          {
            "merk": "MacBook Pro 16\"",
            "brand": "apple",
            "model": "M3 Max",
            "os": "macOS Sonoma",
            "method": "password",
            "registeredAt": "2023-09-10T14:10:00Z",
            "ipAddress": "192.168.1.20",
            "location": {
              "country": "USA",
              "city": "New York",
              "geo": {
                "lat": 40.7128,
                "lng": -74.006
              }
            },
            "lastActive": "2025-01-30T09:15:00Z",
            "status": "trusted"
          }
        ],
        "accessedApps": [
          {
            "name": "VS Code",
            "lastUsed": "2025-01-29T22:10:00Z"
          },
          {
            "name": "GitHub",
            "lastUsed": "2025-01-30T09:00:00Z"
          },
          {
            "name": "Slack",
            "lastUsed": "2025-01-28T15:45:00Z"
          }
        ]
      },
      "fullName": "Johnathan Doe",
      "timestamp": "2025-02-01T04:39:45.823Z",
      "permissions": ["read", "write", "delete"]
    }

Complex Merging of Nested and Dynamic Data

const target = { a: 1, b: { b0: "b0", b1: "b1" } };
const source = { b: { b0: "b0", b2: "b2", b3: "b3" }, e: 4 };
const deepSource = { b: { b4: "b4", b6: "b6" }, f: 4 };
const dynamicSource = [
  { f: { f1: "f1", f2: "f2" } },
  { g: NaN && "g0" }, // like this if you want to use the falsy value of key?.g
  !false && { h: { h1: "h1", h2: "h2" } }, // like this if you want to get valid value
  true && { f: { f3: "f3", f1: "F1" } }
];
const getKeys = (key?: ocxKey) => key && { keys: Object.keys(key) };
 
console.log(
  ocx(
    "ignored",
    target,
    source,
    deepSource,
    () => dynamicSource,
    key => key?.f && { f: { f5: "F5", f2: "F2", f1: "FOO" } },
    getKeys
  )
);
// {
//   a: 1,
//   b: { b0: 'b0', b1: 'b1', b2: 'b2', b3: 'b3', b4: 'b4', b6: 'b6' },
//   e: 4,
//   f: { f1: 'FOO', f2: 'F2', f3: 'f3', f5: 'F5' },
//   h: { h1: 'h1', h2: 'h2' },
//   keys: [ 'a', 'b', 'e', 'f', 'g', 'h' ]
// }

Serialization Example

1. API Response Cleaning & Normalization

const apiResponse = {
  user: "JohnDoe",
  email: null,
  role: "admin",
  metadata: { lastLogin: undefined, verified: true }
};
 
const serialized = ocx(apiResponse);
console.log(serialized);
// { user: "JohnDoe", role: "admin", metadata: { verified: true } }

👉 The clean() function removes null and undefined values ​​from the API response.

2. Query Parameter Serialization

const queryParams = {
  search: "typescript",
  page: 1,
  limit: undefined,
  sort: "desc"
};
 
const serializedQuery = new URLSearchParams(ocx(queryParams)).toString();
console.log(serializedQuery);
// "search=typescript&page=1&sort=desc"

👉 Only valid values ​​are included in the query string.

3. Object Serialization for Caching

const cacheData = {
  id: "123",
  preferences: {
    theme: "dark",
    notifications: false
  },
  timestamp: () => new Date().toISOString()
};
 
const serializedData = JSON.stringify(ocx(cacheData));
console.log(serializedData);
// {"id":"123","preferences":{"theme":"dark"},"timestamp":"2025-02-05T12:34:56.789Z"}

👉 The function in the object is executed, then the object is cleaned up before being serialized.


Complex Serialization Example

const user = { id: 1, name: "Alice", email: "alice@example.com" };
const metadata = () => ({ timestamp: Date.now() });
const flags = { active: true, verified: false };
 
const serialized = ocx(user, metadata, flags);
console.log(serialized);
// {
//   id: 1,
//   name: 'Alice',
//   email: 'alice@example.com',
//   timestamp: 1738340551295,
//   active: true
// }
const data = [
  { id: 1, name: "Alice", active: true, details: { role: "user", age: 25 } },
  {
    id: 2,
    name: "Bob",
    active: false,
    details: { role: "moderator", age: 30 }
  },
  { id: 3, name: "Charlie", active: true, details: { role: "admin", age: 35 } }
];
 
const serialized = data.map(item =>
  ocx(item, { isAdult: item.details.age >= 18 }, key => key?.active && { status: "online" }, !item.active && { status: "offline", inactiveSince: "2023-12-01" })
);
 
console.log(serialized);
  • Result:
    [
      {
        "id": 1,
        "name": "Alice",
        "active": true,
        "details": { "role": "user", "age": 25 },
        "isAdult": true,
        "status": "online"
      },
      {
        "id": 2,
        "name": "Bob",
        "details": { "role": "moderator", "age": 30 },
        "isAdult": true,
        "status": "offline",
        "inactiveSince": "2023-12-01"
      },
      {
        "id": 3,
        "name": "Charlie",
        "active": true,
        "details": { "role": "admin", "age": 35 },
        "isAdult": true,
        "status": "online"
      }
    ]

Handling Symbol Keys in ocx

Why Use Symbol?

  • Uniqueness: Each Symbol is unique, preventing key conflicts.
  • Hidden Properties: Symbol properties are not enumerable, making them useful for metadata.
  • Framework & API Integration: Many libraries and built-in JavaScript functions use Symbol for custom behavior.
    Useful for internal or protected properties.

Example Usage with Symbol

1. Symbol as Object Keys

const metaKey = Symbol("metadata");
const user = {
  name: "Alice",
  age: 25,
  [metaKey]: { role: "admin", hidden: { others: "hiddenValue" } }
};
 
const cleaned = ocx(user);
console.log(cleaned);
// {
//   name: 'Alice',
//   age: 25,
//   [Symbol(metadata)]: { role: 'admin', hidden: { others: 'hiddenValue' } }
// }

2. Merging Objects with Symbol

const symA = Symbol("a");
const symB = Symbol("b");
const obj1 = { [symA]: "Hello", x: 10 };
const obj2 = { [symB]: "World", y: 20 };
 
const merged = ocx(obj1, obj2);
console.log(merged);
// { x: 10, y: 20, [Symbol(a)]: 'Hello', [Symbol(b)]: 'World' }

3. Deep Merging with Symbol

const symA = Symbol("a");
const symB = Symbol("b");
const obj1 = { [symA]: "Hello", x: 10 };
const obj2 = { [symB]: "World", y: 20 };
const deepMerged = ocx(obj1, { y: 10, deep: { obj2 } });
console.log(deepMerged);
// {
//   x: 10,
//   y: 10,
//   deep: { obj2: { y: 20, [Symbol(b)]: 'World' } },
//   [Symbol(a)]: 'Hello'
// }

4. Symbol in Nested Objects

const privateKey = Symbol("private");
 
const obj = {
  name: "John",
  details: {
    age: 30,
    [privateKey]: "Sensitive Data"
  }
};
 
const updated = ocx(obj, { details: { age: 31 } });
console.log(updated);
// {
//   name: 'John',
//   details: { age: 31, [Symbol(private)]: 'Sensitive Data' }
// }

5. Symbol in Node.js (util.inspect.custom)

import util from "util";
const obj = {
  name: "Debug Object",
  [util.inspect.custom]: () => "Custom Output"
};
console.log(util.inspect(ocx(obj)));
// 'Custom Output'

Advantages

  • Simplifies dynamic object creation for configurations or API responses.
  • Supports deep merging of objects.
  • Handles arrays, functions, and dynamic values seamlessly.
  • Filters out unnecessary or falsy values by default behavior.
  • Provides ocx.raw() chaining If you need to keep falsy values ​​while merger (very useful for debugging).
  • Supports Symbol as keys, ensuring metadata persistence.