Ir al contenido

SDK de TypeScript

El SDK de TypeScript de Contismo es el cliente oficial de TypeScript para la API de contenido de GraphQL de Contismo. Úsalo para consultar contenido, ejecutar mutaciones, introspeccionar tu esquema y generar tipos de TypeScript para tu proyecto.

El paquete se publica en npm como @contismo/sdk.

Instala el SDK en tu aplicación:

Terminal window
pnpm add @contismo/sdk

El SDK requiere Node.js 20 o posterior.

El SDK se autentica con una clave de API de GraphQL de Contismo y envía Authorization y el encabezado X-Environment de forma automática.

Las claves de API se crean en el Studio, en Configuración → Claves de API.

Prefijo de la clave Acceso
gql_ Consultas e introspección
gqlw_ Consultas, mutaciones e introspección

Usa una clave gql_ para los clientes de entrega de solo lectura. Usa una clave gqlw_ solo donde tu aplicación necesite crear, actualizar o eliminar contenido.

  1. Crea contismo.config.ts en la raíz de tu proyecto.
  2. Ejecuta pnpm contismo generate para obtener tu esquema y generar los tipos de TypeScript.
  3. Crea un cliente y consulta el contenido con fetch o fetchOne.
import { defineConfig } from "@contismo/sdk/config";
export default defineConfig({
client: {
apiKey: "gql_...",
endpoint: "https://graphql.contismo.com",
environment: "master",
},
});
Terminal window
pnpm contismo generate
import { ContismoClient } from "@contismo/sdk";
import { BlogPost } from "./generated/contismo-models";
const client = new ContismoClient();
const { items: posts } = await client.fetch(BlogPost, {
select: {
_id: true,
title: true,
},
limit: 10,
});

El primer argumento de fetch es el ID de API del modelo de contenido en el Studio, o una referencia de modelo generada desde contismo-models.ts (consulta Consultar contenido).

Las opciones obligatorias del cliente en contismo.config.ts son:

Opción Descripción
apiKey Clave de API de GraphQL del Studio
endpoint Extremo de GraphQL, por lo general https://graphql.contismo.com
environment ID de API del entorno, enviado como X-Environment

Agrega la configuración opcional de codegen cuando quieras cambiar las rutas de salida:

import { defineConfig } from "@contismo/sdk/config";
export default defineConfig({
client: {
apiKey: "gql_...",
endpoint: "https://graphql.contismo.com",
environment: "master",
},
codegen: {
outputDir: "./src/generated",
outputFile: "contismo.ts",
schemaDir: "./contismo",
},
});

De forma predeterminada, pnpm contismo generate escribe:

  • contismo/schema.json
  • src/generated/contismo.ts — tipos de entrada, como Entry_BlogPost
  • contismo-models.ts — registro de modelos, ContismoEntryMap y referencias de modelo tipadas, como BlogPost

Si tu aplicación no usa un archivo de configuración, pasa las credenciales directamente:

import { ContismoClient } from "@contismo/sdk";
const client = new ContismoClient({
apiKey: "gql_...",
endpoint: "https://graphql.contismo.com",
environment: "master",
});

Si tu archivo de configuración está en otro lugar, pasa su ruta:

const client = new ContismoClient({
config: "./config/contismo.config.ts",
});

Usa introspect para leer el esquema de GraphQL de forma programática. Usa las mismas credenciales que las consultas de contenido: una clave de API de GraphQL (gql_ o gqlw_) y un entorno. Si la clave o el entorno son incorrectos, la API devuelve un error de autenticación en lugar de un fallo genérico de introspección.

const schema = await client.introspect();

El SDK también exporta writeIntrospectionResult si quieres escribir el resultado en disco en un flujo personalizado.

Usa fetch para consultar una lista de entradas con un objeto select al estilo de Prisma. fetchOne obtiene una sola entrada por ID.

Después de contismo generate, importa una referencia de modelo desde contismo-models.ts. El tipo de retorno se infiere: no hace falta un genérico explícito.

import { ContismoClient } from "@contismo/sdk";
import { BlogPost } from "./generated/contismo-models";
const client = new ContismoClient();
const { items: posts } = await client.fetch(BlogPost, {
select: {
_id: true,
title: true,
author: {
name: true,
},
},
limit: 10,
});
const post = await client.fetchOne(BlogPost, {
id: "entry-id-here",
select: {
_id: true,
title: true,
},
});

En los campos que devuelven una unión de GraphQL, agrupa cada selección bajo el nombre del tipo miembro generado. El SDK convierte esas claves en fragmentos en línea:

import { ContismoClient } from "@contismo/sdk";
import { Guide } from "./generated/contismo-models";
const client = new ContismoClient();
const guide = await client.fetchOne(Guide, {
id: "guide-id-here",
select: {
title: true,
modularContent: {
Component_Accordion: {
type: true,
items: {
heading: true,
content: { asHtml: true },
},
},
Component_Content: {
content: { asHtml: true },
},
},
},
});

Usa los nombres de miembro de los tipos de esquema generados, como Component_Accordion, Component_Content o Entry_Guide. Las selecciones de unión funcionan tanto con fetch como con fetchOne.

Los campos de recurso de las entradas devuelven URL de la CDN. Selecciona url y thumbnailUrl, y luego usa buildCdnUrl para agregar transformaciones de imagen:

import { ContismoClient, buildCdnUrl } from "@contismo/sdk";
import { BlogPost } from "./generated/contismo-models";
const client = new ContismoClient();
const { items: posts } = await client.fetch(BlogPost, {
select: {
_id: true,
title: true,
cover: {
url: true,
thumbnailUrl: true,
},
},
limit: 10,
});
const cover = posts[0]?.cover;
const previewUrl = cover?.thumbnailUrl ?? cover?.url;
const heroUrl = cover?.url
? buildCdnUrl(cover.url, {
w: 1200,
fmt: "webp",
q: 80,
})
: null;

La entrega por CDN es pública: las solicitudes GET no necesitan una clave de API. Prefiere thumbnailUrl para las vistas previas de listas y tarjetas cuando esté presente. Usa la url completa con transformaciones para la imagen principal.

Para la referencia completa de los parámetros de transformación, consulta la guía de CDN de imágenes.

Usa query cuando quieras proporcionar tú mismo el documento de GraphQL:

const data = await client.query(
`
query BlogPost($id: ID!) {
blogPost(id: $id) {
_id
title
}
}
`,
{ id: "entry-id-here" },
);

Esto es útil cuando quieres control total de la operación o cuando copias una consulta del Explorador GraphQL.

Las mutaciones requieren una clave de API de lectura y escritura con el prefijo gqlw_. El SDK bloquea las llamadas a client.mutate() antes de hacer una solicitud de red cuando el cliente está configurado con una clave de solo lectura gql_. Las mutaciones de entradas de contenido usan {ModelApiId}Input (por ejemplo, BlogPostInput) tanto para crear como para actualizar, no {ModelApiId}CreateInput.

const client = new ContismoClient({
apiKey: "gqlw_...",
endpoint: "https://graphql.contismo.com",
environment: "master",
});
await client.mutate(
`
mutation CreatePost($input: BlogPostInput!) {
createBlogPost(input: $input) {
_id
_status
title
}
}
`,
{
input: {
title: "Hello world",
},
},
);

Para las formas de las mutaciones y los nombres de operación generados, consulta la referencia de la API GraphQL.

Las entradas que faltan no lanzan un error. Las lecturas singulares, como blogPost(id: …) y client.fetchOne(), devuelven null cuando ninguna entrada coincide (ID, configuración regional o filtros de estado incorrectos). Revisa el resultado en lugar de usar try/catch:

const client = new ContismoClient();
const post = await client.fetchOne("BlogPost", {
id: entryId,
select: { _id: true, title: true },
});
if (post == null) {
// Entry does not exist or does not match filters
}

Los fallos de GraphQL, HTTP y del SDK sí lanzan un error. Los errores de configuración, de validación, de autenticación, los límites de frecuencia y otros errors de la API rechazan la promesa como ContismoError (a menudo ContismoGraphQLError). Usa isContismoError para manejarlos:

import {
ContismoClient,
ContismoGraphQLError,
isContismoError,
} from "@contismo/sdk";
const client = new ContismoClient();
try {
await client.query(`query { blogPostCollection { items { _id } } }`);
} catch (error) {
if (isContismoError(error) && error instanceof ContismoGraphQLError) {
console.error(error.code, error.message);
}
}

Esto captura los fallos de solicitud de la API, no un campo singular null cuando falta un ID.