# dotexists

**Check if a path exists in nested data**

Part of the Truth pillar, `dotexists` is the most fundamental boolean operation - checking whether a path exists in a data structure.

## Overview

`dotexists` safely navigates through nested dictionaries and lists to determine if a path exists, regardless of the value at that path.

## Basic Usage

```python
from truth.dotexists import check

data = {
    "user": {
        "name": "Alice",
        "email": "alice@example.com",
        "age": None
    }
}

# Check if paths exist
check(data, "user.name")        # True
check(data, "user.email")       # True
check(data, "user.age")         # True (even though value is None)
check(data, "user.phone")       # False
```

## Important: Existence vs Truthiness

`dotexists` returns `True` if the path exists, even if the value is falsy:

```python
data = {
    "count": 0,
    "active": False,
    "name": "",
    "value": None,
    "items": []
}

# All these return True (paths exist)
check(data, "count")    # True (even though 0 is falsy)
check(data, "active")   # True (even though False)
check(data, "name")     # True (even though empty string)
check(data, "value")    # True (even though None)
check(data, "items")    # True (even though empty list)
```

## List Access

Works with list indices:

```python
data = {
    "users": [
        {"name": "Alice"},
        {"name": "Bob"},
        {"name": "Charlie"}
    ]
}

check(data, "users.0")       # True
check(data, "users.2.name")  # True
check(data, "users.3")       # False (out of bounds)
check(data, "users.-1")      # True (negative indexing)
```

## Safe Navigation Pattern

Use `dotexists` for safe navigation before accessing values:

```python
from depth.dotget import get
from truth.dotexists import check

def safe_get(data, path, default=None):
    """Get value if path exists, otherwise return default."""
    if check(data, path):
        return get(data, path)
    return default

# Usage
config = {"database": {"host": "localhost"}}
port = safe_get(config, "database.port", 5432)  # Returns 5432 (default)
```

## Real-World Examples

### Optional Configuration
```python
config = {
    "server": {
        "host": "localhost",
        "port": 8080
        # SSL config is optional
    }
}

# Check for optional settings
if check(config, "server.ssl.enabled"):
    # Configure SSL
    pass
else:
    # Use default (no SSL)
    pass
```

### Feature Detection
```python
user_data = {
    "profile": {
        "name": "Alice",
        "premium_features": {
            "advanced_analytics": True
        }
    }
}

# Check if user has premium features
has_premium = check(user_data, "profile.premium_features")
has_analytics = check(user_data, "profile.premium_features.advanced_analytics")
```

## Mathematical Foundation

`dotexists` implements the membership test (∈) for paths in nested structures:
- Returns `True` ⟺ path ∈ structure
- Returns `False` ⟺ path ∉ structure

## Command Line

`dotexists` uses exit codes for boolean output: exit code `0` means the path exists, exit code `1` means it does not. No output is printed to stdout.

```bash
# Check if a path exists in a JSON file
dotexists user.name data.json
echo $?  # 0 if exists, 1 if not

# Read from stdin (default)
echo '{"user": {"name": "Alice"}}' | dotexists user.name
echo $?  # 0

# Check a missing path
echo '{"user": {"name": "Alice"}}' | dotexists user.email
echo $?  # 1

# Use in shell conditionals
if dotexists server.ssl.enabled config.json; then
    echo "SSL is configured"
else
    echo "No SSL configuration found"
fi

# YAML input (inferred from file extension)
dotexists database.host config.yaml

# Force input format
dotexists user.name data.txt --in yaml
```

### Options

| Flag | Description |
|------|-------------|
| `path` | The exact dot-path to check for existence (e.g., `user.name`). Required. |
| `data_file` | Path to the JSON or YAML data file, or `-` for stdin (default). |
| `--in`, `--input-format` | Format of the input data: `json` or `yaml`. Inferred from file extension if not provided. Defaults to `json` for stdin. |

### Exit Codes

| Code | Meaning |
|------|---------|
| `0` | Path exists in the data |
| `1` | Path does not exist, or an error occurred |

## Related Tools

- **[dotget](../depth/dotget.md)** - Extract values from paths
- **[dotequals](dotequals.md)** - Check if path has specific value
- **[dotquery](dotquery.md)** - Complex boolean queries