CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-contentful

Client for Contentful's Content Delivery API

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

querying.mddocs/

Content Querying

Advanced querying capabilities for filtering, searching, and retrieving specific content with type-safe parameter validation and comprehensive query operators.

Capabilities

Basic Query Parameters

Core query parameters available for most content retrieval operations.

interface BaseQueries {
  /** Limit number of results (max: 1000, default: 100) */
  limit?: number;
  /** Skip entries for pagination (max: 9000) */
  skip?: number;
  /** Order results by field (prefix with - for descending) */
  order?: string;
  /** Specify locale (default: default locale of space) */
  locale?: string;
  /** Select specific fields to return */
  select?: string;
  /** Include linked entries and assets (default: 1, max: 10) */
  include?: number;
}

Search Queries

Full-text search capabilities across content fields.

interface SearchQueries {
  /** Full-text search across all text fields */
  query?: string;
}

Usage Examples:

// Basic full-text search
const searchResults = await client.getEntries({
  query: "JavaScript tutorial"
});

// Search within specific content type
const blogSearchResults = await client.getEntries({
  content_type: "blogPost",
  query: "React hooks"
});

Field Equality Queries

Filter content by exact field values.

interface EqualityQueries {
  /** Filter by exact field value */
  [key: `fields.${string}`]: any;
  /** Filter by system property */
  [key: `sys.${string}`]: any;
}

Usage Examples:

// Filter by field values
const featuredPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.featured": true,
  "fields.category": "Technology"
});

// Filter by system properties
const recentEntries = await client.getEntries({
  "sys.createdAt[gte]": "2023-01-01T00:00:00Z"
});

Existence Queries

Check for the presence or absence of field values.

interface ExistenceQueries {
  /** Check if field exists and has a value */
  [key: `fields.${string}[exists]`]: boolean;
  /** Check if system property exists */
  [key: `sys.${string}[exists]`]: boolean;
}

Usage Examples:

// Find entries with specific fields present
const entriesWithImages = await client.getEntries({
  content_type: "blogPost",
  "fields.featuredImage[exists]": true
});

// Find entries missing certain fields
const drafts = await client.getEntries({
  content_type: "blogPost",
  "fields.publishDate[exists]": false
});

Range Queries

Filter content using range comparisons for numbers and dates.

interface RangeQueries {
  /** Greater than */
  [key: `fields.${string}[gt]`]: string | number;
  /** Greater than or equal */
  [key: `fields.${string}[gte]`]: string | number;
  /** Less than */
  [key: `fields.${string}[lt]`]: string | number;
  /** Less than or equal */
  [key: `fields.${string}[lte]`]: string | number;
  /** System property range queries */
  [key: `sys.${string}[gt]`]: string | number;
  [key: `sys.${string}[gte]`]: string | number;
  [key: `sys.${string}[lt]`]: string | number;
  [key: `sys.${string}[lte]`]: string | number;
}

Usage Examples:

// Date range queries
const recentPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.publishDate[gte]": "2023-01-01",
  "fields.publishDate[lte]": "2023-12-31"
});

// Numeric range queries
const expensiveProducts = await client.getEntries({
  content_type: "product",
  "fields.price[gt]": 100,
  "fields.price[lte]": 1000
});

Set Queries

Filter content using set operations (in/nin).

interface SetQueries {
  /** Field value is in the provided array */
  [key: `fields.${string}[in]`]: string[];
  /** Field value is not in the provided array */
  [key: `fields.${string}[nin]`]: string[];
  /** System property set queries */
  [key: `sys.${string}[in]`]: string[];
  [key: `sys.${string}[nin]`]: string[];
}

Usage Examples:

// Include multiple categories
const techAndDesignPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.category[in]": ["Technology", "Design", "Development"]
});

// Exclude specific content
const nonDraftEntries = await client.getEntries({
  content_type: "blogPost",
  "fields.status[nin]": ["draft", "archived"]
});

Subset Queries

Filter arrays and check for matches within array fields.

interface SubsetQueries {
  /** All array items match the query */
  [key: `fields.${string}[all]`]: string[];
  /** Some array items match the query */
  [key: `fields.${string}[in]`]: string[];
  /** No array items match the query */
  [key: `fields.${string}[nin]`]: string[];
}

Usage Examples:

// Entries with all specified tags
const wellTaggedPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.tags[all]": ["javascript", "tutorial"]
});

// Entries with some of the specified tags
const relatedPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.tags[in]": ["react", "vue", "angular"]
});

Reference Queries

Filter content by linked entries and assets.

interface ReferenceQueries {
  /** Links to specific entry */
  [key: `fields.${string}.sys.id`]: string;
  /** Links to entry of specific content type */
  [key: `fields.${string}.sys.contentType.sys.id`]: string;
  /** Links to any of the specified entries */
  [key: `fields.${string}[in]`]: string[];
  /** Doesn't link to any of the specified entries */
  [key: `fields.${string}[nin]`]: string[];
}

Usage Examples:

// Find entries linked to specific author
const authorPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.author.sys.id": "author-id"
});

// Find entries linked to authors of specific type
const postsWithPersonAuthors = await client.getEntries({
  content_type: "blogPost",
  "fields.author.sys.contentType.sys.id": "person"
});

// Find entries linked to any of several categories
const categorizedPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.category[in]": ["cat1", "cat2", "cat3"]
});

Location Queries

Filter content by geographical proximity (for Location fields).

interface LocationQueries {
  /** Find entries near coordinates */
  [key: `fields.${string}[near]`]: string; // "lat,lon"
  /** Find entries within bounding box */
  [key: `fields.${string}[within]`]: string; // "lat1,lon1,lat2,lon2"
}

Usage Examples:

// Find locations near New York City
const nearbyLocations = await client.getEntries({
  content_type: "venue",
  "fields.location[near]": "40.7128,-74.0060"
});

// Find locations within a bounding box
const locationsInArea = await client.getEntries({
  content_type: "venue",
  "fields.location[within]": "40.7,-74.1,40.8,-73.9"
});

Order Queries

Control result ordering with multiple fields and directions.

interface OrderQueries {
  /** Order by field (prefix with - for descending) */
  order?: string | string[];
}

Usage Examples:

// Order by single field
const orderedPosts = await client.getEntries({
  content_type: "blogPost",
  order: "-fields.publishDate" // Descending
});

// Multiple ordering criteria
const complexOrdered = await client.getEntries({
  content_type: "blogPost",
  order: ["fields.featured", "-fields.publishDate"]
});

// Order by system properties
const byCreation = await client.getEntries({
  order: "-sys.createdAt"
});

Select Queries

Optimize responses by selecting only needed fields.

interface SelectQueries {
  /** Comma-separated list of fields to include */
  select?: string;
}

Usage Examples:

// Select only specific fields
const minimalEntries = await client.getEntries({
  content_type: "blogPost",
  select: "fields.title,fields.slug,sys.id"
});

// Select nested fields
const authorNames = await client.getEntries({
  content_type: "blogPost",
  select: "fields.title,fields.author.fields.name"
});

// Select system fields
const systemInfo = await client.getEntries({
  select: "sys.id,sys.createdAt,sys.updatedAt"
});

Advanced Querying Patterns

Combining Multiple Query Types

// Complex query combining multiple filters
const complexQuery = await client.getEntries({
  content_type: "blogPost",
  query: "JavaScript",                           // Full-text search
  "fields.category": "Technology",               // Exact match
  "fields.publishDate[gte]": "2023-01-01",      // Range query
  "fields.featured": true,                       // Boolean filter
  "fields.tags[in]": ["tutorial", "beginner"],  // Set query
  "fields.author[exists]": true,                 // Existence check
  order: ["-fields.publishDate", "fields.title"], // Multi-field ordering
  limit: 20,                                     // Pagination
  skip: 0,
  include: 2                                     // Include linked content
});

Pagination Patterns

// Implement pagination
async function getAllEntries(contentType: string, batchSize: number = 100) {
  const allEntries = [];
  let skip = 0;
  let hasMore = true;

  while (hasMore) {
    const batch = await client.getEntries({
      content_type: contentType,
      limit: batchSize,
      skip: skip
    });

    allEntries.push(...batch.items);
    skip += batchSize;
    hasMore = batch.items.length === batchSize;
  }

  return allEntries;
}

Dynamic Query Building

// Build queries dynamically
function buildQuery(filters: Record<string, any>): any {
  const query: any = {};

  Object.entries(filters).forEach(([key, value]) => {
    if (value !== undefined && value !== null && value !== '') {
      if (Array.isArray(value)) {
        query[`${key}[in]`] = value;
      } else if (typeof value === 'object' && value.operator) {
        query[`${key}[${value.operator}]`] = value.value;
      } else {
        query[key] = value;
      }
    }
  });

  return query;
}

// Usage
const dynamicQuery = buildQuery({
  content_type: "blogPost",
  "fields.category": "Technology",
  "fields.publishDate": { operator: "gte", value: "2023-01-01" },
  "fields.tags": ["javascript", "tutorial"]
});

const results = await client.getEntries(dynamicQuery);

Query Validation and Error Handling

// Validate query parameters
function validateQuery(query: any): string[] {
  const errors = [];

  if (query.limit && (query.limit < 1 || query.limit > 1000)) {
    errors.push("Limit must be between 1 and 1000");
  }

  if (query.skip && query.skip > 9000) {
    errors.push("Skip cannot exceed 9000");
  }

  if (query.include && (query.include < 0 || query.include > 10)) {
    errors.push("Include must be between 0 and 10");
  }

  return errors;
}

// Use validation
const query = {
  content_type: "blogPost",
  limit: 50,
  include: 2
};

const validationErrors = validateQuery(query);
if (validationErrors.length > 0) {
  console.error("Query validation errors:", validationErrors);
} else {
  const results = await client.getEntries(query);
}

docs

assets.md

client.md

entries.md

index.md

querying.md

space-content-types.md

sync.md

tags-taxonomy.md

tile.json