Client for Contentful's Content Delivery API
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Access to space metadata, content types, locales, tags, concepts, and other Contentful configuration information for understanding and working with your Contentful space structure.
Fetches metadata about the current Contentful space.
/**
* Fetches the space which the client is currently configured to use
* @returns Promise for the space
*/
getSpace(): Promise<Space>;
interface Space {
sys: {
type: 'Space';
id: string;
version: number;
createdAt: string;
updatedAt: string;
};
name: string;
locales: LocaleDefinition[];
defaultLocale: string;
}
interface LocaleDefinition {
code: string;
name: string;
default: boolean;
fallbackCode?: string;
optional: boolean;
}Usage Example:
// Get space information
const space = await client.getSpace();
console.log(`Space: ${space.name} (${space.sys.id})`);
console.log(`Default locale: ${space.defaultLocale}`);
console.log('Available locales:');
space.locales.forEach(locale => {
console.log(`- ${locale.name} (${locale.code})${locale.default ? ' [default]' : ''}`);
});Fetches available locales for the space.
/**
* Fetches a collection of locales
* @returns Promise for a collection of locales
*/
getLocales(): Promise<LocaleCollection>;
type LocaleCollection = ContentfulCollection<Locale>;
interface Locale {
sys: {
type: 'Locale';
id: string;
version: number;
createdAt: string;
updatedAt: string;
};
code: string;
name: string;
default: boolean;
fallbackCode?: string;
optional: boolean;
}Usage Example:
// Get all locales
const locales = await client.getLocales();
console.log(`Total locales: ${locales.total}`);
locales.items.forEach(locale => {
console.log(`${locale.name} (${locale.code})`);
if (locale.fallbackCode) {
console.log(` Fallback: ${locale.fallbackCode}`);
}
});Retrieve content type definitions and metadata.
/**
* Fetches a content type by ID
* @param id - The content type's ID
* @returns Promise for a content type
*/
getContentType(id: string): Promise<ContentType>;
/**
* Fetches a collection of content types
* @param query - Optional query parameters
* @returns Promise for a collection of content types
*/
getContentTypes(query?: { query?: string }): Promise<ContentTypeCollection>;
interface ContentType {
sys: {
type: 'ContentType';
id: string;
version: number;
space: { sys: { type: 'Link'; linkType: 'Space'; id: string } };
environment: { sys: { type: 'Link'; linkType: 'Environment'; id: string } };
createdAt: string;
updatedAt: string;
};
name: string;
description?: string;
displayField?: string;
fields: ContentTypeField[];
}
interface ContentTypeField {
id: string;
name: string;
type: FieldType;
localized: boolean;
required: boolean;
validations: FieldValidation[];
disabled: boolean;
omitted: boolean;
linkType?: 'Asset' | 'Entry';
items?: {
type: FieldType;
linkType?: 'Asset' | 'Entry';
validations: FieldValidation[];
};
}
type FieldType =
| 'Symbol'
| 'Text'
| 'Integer'
| 'Number'
| 'Date'
| 'Boolean'
| 'Object'
| 'Location'
| 'RichText'
| 'Array'
| 'Link'
| 'ResourceLink';
type ContentTypeCollection = ContentfulCollection<ContentType>;Usage Examples:
// Get specific content type
const blogPostType = await client.getContentType('blogPost');
console.log(`Content Type: ${blogPostType.name}`);
console.log(`Description: ${blogPostType.description}`);
console.log(`Display Field: ${blogPostType.displayField}`);
// Analyze fields
blogPostType.fields.forEach(field => {
console.log(`Field: ${field.name} (${field.id})`);
console.log(` Type: ${field.type}`);
console.log(` Required: ${field.required}`);
console.log(` Localized: ${field.localized}`);
if (field.linkType) {
console.log(` Links to: ${field.linkType}`);
}
});
// Get all content types
const allContentTypes = await client.getContentTypes();
console.log(`Total content types: ${allContentTypes.total}`);
allContentTypes.items.forEach(contentType => {
console.log(`- ${contentType.name} (${contentType.sys.id})`);
});
// Search content types
const searchResults = await client.getContentTypes({
query: 'blog'
});Retrieve and work with content tags.
/**
* Fetches a tag by ID
* @param id - The tag's ID
* @returns Promise for a tag
*/
getTag(id: string): Promise<Tag>;
/**
* Gets a collection of tags
* @param query - Optional query parameters
* @returns Promise for a collection of tags
*/
getTags(query?: TagQueries): Promise<TagCollection>;
interface Tag {
sys: {
type: 'Tag';
id: string;
version: number;
space: { sys: { type: 'Link'; linkType: 'Space'; id: string } };
environment: { sys: { type: 'Link'; linkType: 'Environment'; id: string } };
createdAt: string;
updatedAt: string;
};
name: string;
}
interface TagQueries {
/** Search tag names */
name?: string;
/** Limit results */
limit?: number;
/** Skip results for pagination */
skip?: number;
}
type TagCollection = ContentfulCollection<Tag>;Usage Examples:
// Get specific tag
const tag = await client.getTag('tag-id');
console.log(`Tag: ${tag.name}`);
// Get all tags
const allTags = await client.getTags();
console.log(`Total tags: ${allTags.total}`);
// Search tags by name
const searchTags = await client.getTags({
name: 'javascript'
});
// Paginate through tags
const tagPage = await client.getTags({
limit: 10,
skip: 20
});Retrieve concepts for taxonomy and content organization.
/**
* Fetches a concept by ID
* @param id - The concept's ID
* @returns Promise for a concept
*/
getConcept(id: string): Promise<Concept<'en-US'>>;
/**
* Fetches a collection of concepts
* @param query - Optional query parameters
* @returns Promise for a collection of concepts
*/
getConcepts(query?: ConceptsQueries): Promise<ConceptCollection<'en-US'>>;
interface Concept<Locales extends LocaleCode> {
sys: {
type: 'TaxonomyConcept';
id: string;
version: number;
space: { sys: { type: 'Link'; linkType: 'Space'; id: string } };
environment: { sys: { type: 'Link'; linkType: 'Environment'; id: string } };
createdAt: string;
updatedAt: string;
};
prefLabel: LocalizedField<Locales>;
altLabels?: LocalizedField<Locales>[];
hiddenLabels?: LocalizedField<Locales>[];
definition?: LocalizedField<Locales>;
editorialNote?: LocalizedField<Locales>;
notation?: string;
broader?: ConceptLink[];
narrower?: ConceptLink[];
related?: ConceptLink[];
}
interface ConceptsQueries {
/** Search concepts */
query?: string;
/** Limit results */
limit?: number;
/** Skip results for pagination */
skip?: number;
}
type ConceptCollection<Locales extends LocaleCode> = ContentfulCollection<Concept<Locales>>;Usage Examples:
// Get specific concept
const concept = await client.getConcept('concept-id');
console.log(`Concept: ${concept.prefLabel['en-US']}`);
if (concept.definition) {
console.log(`Definition: ${concept.definition['en-US']}`);
}
// Get all concepts
const allConcepts = await client.getConcepts();
console.log(`Total concepts: ${allConcepts.total}`);
// Search concepts
const searchResults = await client.getConcepts({
query: 'technology'
});Retrieve concept schemes for organizing taxonomies.
/**
* Fetches a concept scheme by ID
* @param id - The concept scheme's ID
* @returns Promise for a concept scheme
*/
getConceptScheme(id: string): Promise<ConceptScheme<'en-US'>>;
/**
* Fetches a collection of concept schemes
* @param query - Optional query parameters
* @returns Promise for a collection of concept schemes
*/
getConceptSchemes(query?: ConceptSchemesQueries): Promise<ConceptSchemeCollection<'en-US'>>;
interface ConceptScheme<Locales extends LocaleCode> {
sys: {
type: 'TaxonomyConceptScheme';
id: string;
version: number;
space: { sys: { type: 'Link'; linkType: 'Space'; id: string } };
environment: { sys: { type: 'Link'; linkType: 'Environment'; id: string } };
createdAt: string;
updatedAt: string;
};
prefLabel: LocalizedField<Locales>;
definition?: LocalizedField<Locales>;
topConcepts?: ConceptLink[];
}
interface ConceptSchemesQueries {
/** Search concept schemes */
query?: string;
/** Limit results */
limit?: number;
/** Skip results for pagination */
skip?: number;
}
type ConceptSchemeCollection<Locales extends LocaleCode> = ContentfulCollection<ConceptScheme<Locales>>;Usage Example:
// Get specific concept scheme
const scheme = await client.getConceptScheme('scheme-id');
console.log(`Scheme: ${scheme.prefLabel['en-US']}`);
// Get all concept schemes
const allSchemes = await client.getConceptSchemes();
console.log(`Total schemes: ${allSchemes.total}`);interface ConceptLink {
sys: {
type: 'Link';
linkType: 'TaxonomyConcept';
id: string;
};
}
interface LocalizedField<Locales extends LocaleCode> {
[locale: string]: string;
}
interface ContentTypeLink {
type: 'Link';
linkType: 'ContentType';
id: string;
}interface FieldValidation {
/** Link validation */
linkContentType?: string[];
/** In validation for predefined values */
in?: (string | number)[];
/** Link validation for mime type groups */
linkMimetypeGroup?: string[];
/** Size validation */
size?: {
min?: number;
max?: number;
};
/** Range validation */
range?: {
min?: number;
max?: number;
};
/** Regex validation */
regexp?: {
pattern: string;
flags?: string;
};
/** Prohibit regex validation */
prohibitRegexp?: {
pattern: string;
flags?: string;
};
/** Unique validation */
unique?: boolean;
/** Date range validation */
dateRange?: {
min?: string;
max?: string;
};
/** Asset file size validation */
assetFileSize?: {
min?: number;
max?: number;
};
/** Asset image dimensions validation */
assetImageDimensions?: {
width?: {
min?: number;
max?: number;
};
height?: {
min?: number;
max?: number;
};
};
}// Generate form fields based on content type
async function generateFormFields(contentTypeId: string) {
const contentType = await client.getContentType(contentTypeId);
const formFields = contentType.fields.map(field => {
const fieldConfig = {
id: field.id,
name: field.name,
type: field.type,
required: field.required,
localized: field.localized
};
// Add validation rules
const validations = field.validations || [];
validations.forEach(validation => {
if (validation.size) {
fieldConfig.minLength = validation.size.min;
fieldConfig.maxLength = validation.size.max;
}
if (validation.range) {
fieldConfig.min = validation.range.min;
fieldConfig.max = validation.range.max;
}
if (validation.in) {
fieldConfig.options = validation.in;
}
});
return fieldConfig;
});
return formFields;
}// Analyze content type usage and complexity
async function analyzeContentTypes() {
const contentTypes = await client.getContentTypes();
const analysis = contentTypes.items.map(contentType => {
const fieldCount = contentType.fields.length;
const requiredFields = contentType.fields.filter(f => f.required).length;
const localizedFields = contentType.fields.filter(f => f.localized).length;
const linkFields = contentType.fields.filter(f => f.type === 'Link').length;
return {
id: contentType.sys.id,
name: contentType.name,
complexity: {
totalFields: fieldCount,
requiredFields,
localizedFields,
linkFields,
complexity: fieldCount > 10 ? 'high' : fieldCount > 5 ? 'medium' : 'low'
}
};
});
return analysis;
}// Implement locale fallback logic
function resolveLocalizedValue<T>(
localizedField: Record<string, T>,
requestedLocale: string,
locales: Locale[]
): T | null {
// Try requested locale first
if (localizedField[requestedLocale]) {
return localizedField[requestedLocale];
}
// Find locale configuration
const localeConfig = locales.find(l => l.code === requestedLocale);
// Try fallback locale
if (localeConfig?.fallbackCode && localizedField[localeConfig.fallbackCode]) {
return localizedField[localeConfig.fallbackCode];
}
// Try default locale
const defaultLocale = locales.find(l => l.default);
if (defaultLocale && localizedField[defaultLocale.code]) {
return localizedField[defaultLocale.code];
}
// Return first available value
const availableLocales = Object.keys(localizedField);
if (availableLocales.length > 0) {
return localizedField[availableLocales[0]];
}
return null;
}
// Usage
const locales = await client.getLocales();
const entry = await client.withAllLocales.getEntry('entry-id');
const title = resolveLocalizedValue(
entry.fields.title,
'fr-FR',
locales.items
);