Skip to main content
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

query GetPackageData($id: ID!) {
  resolvedPackageData(id: $id) {
    id
    version
    components
    assets
  }
}

Parameters

ParameterTypeRequiredDescription
idID!YesContent-addressed package ID (SHA-256 hash)

Example

query {
  resolvedPackageData(id: "abc123def456...") {
    id
    version
    components
    assets
  }
}
Response:
{
  "data": {
    "resolvedPackageData": {
      "id": "abc123def456...",
      "version": "1.0.0",
      "components": "{\"ArticleLayout\":\"const body = ...\",\"ProductCard\":\"const body = ...\"}",
      "assets": "{\"ArticleLayout\":[{\"name\":\"hero\",\"url\":\"...\"}]}"
    }
  }
}

ResolvedPackageData Fields

FieldTypeDescription
idID!Content-addressed SHA-256 hash
versionString!Semantic version
componentsStringJSON object mapping component names to compiled code
assetsStringJSON object mapping component names to asset arrays

Usage Pattern

This query is typically used with resolvedRef for efficient caching:

Step 1: Fetch Content with References

query GetContentWithCaching($id: ID!) {
  content(id: $id) {
    id
    name
    compiled
    resolvedRef {
      package
      dependencies
    }
  }
}

Step 2: Check Cache and Fetch Missing Packages

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: { 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

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 AWS 128KB 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:
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;
}
See the Caching documentation for a complete guide to implementing normalized package caching.