> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metabind.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Package Data

> Fetch resolved package data for caching

The `resolvedPackageData` query fetches package data by its content-addressed ID. This is used with the normalized caching pattern to efficiently retrieve package data that may be shared across multiple content items.

## Query

```graphql theme={null}
query GetPackageData($packageId: ID!) {
  resolvedPackageData(packageId: $packageId) {
    id
    version
    components
    assets
    cdnUrl
  }
}
```

### Parameters

| Parameter   | Type | Required | Description                                 |
| ----------- | ---- | -------- | ------------------------------------------- |
| `packageId` | ID!  | Yes      | Content-addressed package ID (SHA-256 hash) |

### Example

```graphql theme={null}
query {
  resolvedPackageData(packageId: "abc123def456...") {
    id
    version
    components
    assets
    cdnUrl
  }
}
```

Response:

```json theme={null}
{
  "data": {
    "resolvedPackageData": {
      "id": "abc123def456...",
      "version": "1.0.0",
      "components": "{\"ArticleLayout\":\"const body = ...\",\"ProductCard\":\"const body = ...\"}",
      "assets": "{\"ArticleLayout\":[{\"name\":\"hero\",\"url\":\"...\"}]}",
      "cdnUrl": "https://cdn.metabind.ai/packages/abc123def456..."
    }
  }
}
```

## ResolvedPackageData Fields

| Field        | Type    | Description                                          |
| ------------ | ------- | ---------------------------------------------------- |
| `id`         | ID!     | Content-addressed SHA-256 hash                       |
| `version`    | String! | Semantic version                                     |
| `components` | String! | JSON object mapping component names to compiled code |
| `assets`     | String! | JSON object mapping component names to asset arrays  |
| `cdnUrl`     | String  | CDN URL for fetching package data                    |

## Usage Pattern

This query is typically used with `resolvedRef` for efficient caching:

### Step 1: Fetch Content with References

```graphql theme={null}
query GetContentWithCaching($id: ID!) {
  content(id: $id) {
    id
    name
    compiled
    resolvedRef {
      package
      dependencies
    }
  }
}
```

### Step 2: Check Cache and Fetch Missing Packages

```javascript theme={null}
const packageCache = new Map();

async function getPackageData(id) {
  // Check cache first
  if (packageCache.has(id)) {
    return packageCache.get(id);
  }

  // Fetch from API
  const { data } = await client.query({
    query: GET_PACKAGE_DATA,
    variables: { packageId: id }
  });

  // Cache the result (content-addressed, so safe to cache forever)
  packageCache.set(id, data.resolvedPackageData);
  return data.resolvedPackageData;
}

async function fetchMissingPackages(ids) {
  const missing = ids.filter(id => !packageCache.has(id));

  // Batch fetch missing packages
  const results = await Promise.all(
    missing.map(id => getPackageData(id))
  );

  return results;
}
```

### Step 3: Load Content with Cached Packages

```javascript theme={null}
async function loadContent(id) {
  // Fetch content with references only
  const { data } = await client.query({
    query: GET_CONTENT_WITH_CACHING,
    variables: { id }
  });

  const content = data.content;

  // Fetch any missing package data
  const packageIds = [
    content.resolvedRef.package,
    ...content.resolvedRef.dependencies
  ];

  await fetchMissingPackages(packageIds);

  // Now render with cached packages
  renderContent(content, packageCache);
}
```

## Benefits

1. **Smaller Payloads**: Content responses only include package IDs, not full data
2. **Efficient Caching**: Content-addressed IDs mean packages never change
3. **Shared Data**: Multiple content items referencing the same package share cached data
4. **WebSocket Compliance**: Subscription payloads stay under 100KB limit
5. **Reduced Bandwidth**: Only fetch packages once, regardless of how many content items use them

## Draft Packages

Draft packages use a special ID format and should not be cached long-term:

```javascript theme={null}
function isDraftPackage(id) {
  return id.startsWith('draft:');
}

async function getPackageData(id) {
  // Draft packages should not be cached long-term
  if (isDraftPackage(id)) {
    return await fetchPackageData(id);
  }

  // Published packages can be cached forever
  if (packageCache.has(id)) {
    return packageCache.get(id);
  }

  const data = await fetchPackageData(id);
  packageCache.set(id, data);
  return data;
}
```

<Note>
  See the [Caching](/graphql/caching) documentation for a complete guide to implementing normalized package caching.
</Note>
