API de diffusion GraphQL
Quelles requêtes existent, comment fonctionne le cadrage par espace de travail, et lesquelles le SDK encapsule plutôt que vous.
cmssy sert le contenu publié via un unique endpoint GraphQL. Le SDK encapsule déjà les lectures courantes - pages, layouts, configuration du site, formulaires - si bien que la plupart des applications n'écrivent jamais de requête. Pour le reste (modèles personnalisés, enregistrements, listes de pages enfants), vous envoyez la vôtre via le client de diffusion.
Endpoint et cadrage
Les lectures publiques passent par le chemin incluant l'organisation :
{apiBase}/public/{orgSlug}/{workspaceSlug}/graphqlapiBase est votre apiUrl privé de son /graphql final - par défaut https://api.cmssy.io, les requêtes arrivent donc sur https://api.cmssy.io/public/{org}/{ws}/graphql. Ne redéfinissez apiUrl qu'en auto-hébergement. org et workspaceSlug viennent de votre configuration, et le SDK assemble le chemin.
Comme l'organisation figure dans le chemin, un slug d'espace de travail ne doit être unique qu'au sein de son organisation.
Deux façons de cadrer une requête
Chaque opération est cadrée par espace de travail, mais pas toutes de la même manière. C'est le détail sur lequel on trébuche :
workspaceSlug(String!) - pour les lectures de pages, layouts, configuration et formulaires. Les helpers du SDK le transmettent automatiquement depuis votre configuration.workspaceId(String!) - pour les lectures de modèles, d'enregistrements et de pages par type. Appelezclient.queryScoped(...): si votre requête déclare$workspaceIdet que vous ne le passez pas, le SDK le résout depuisworkspaceSluget injecte la variable et l'en-têtex-workspace-id.
// $workspaceId est rempli pour vous
await client.queryScoped(MY_QUERY, { modelSlug: "products", limit: 20 });Ce que le SDK encapsule déjà
Vous n'écrivez normalement jamais ces requêtes : le helper indiqué les appelle pour vous.
publicPage→fetchPage- renvoie{ id, blocks, publishedBlocks }.publicPageById→fetchPageById- renvoie{ id, publishedBlocks }.publicPages→fetchPages- renvoie[{ id, slug, updatedAt, publishedAt }].publicPage(champs SEO) →fetchPageMeta- renvoie{ id, seoTitle, seoDescription, seoKeywords, displayName }.publicPageLayouts→fetchLayouts- renvoie[{ position, blocks }].publicSiteConfig→fetchSiteConfig/resolveSiteLocales- nom du site, locales, fonctionnalités, branding.public.form.get→resolveForms(etcontext.forms) - champs et réglages du formulaire.public.form.submit→SUBMIT_FORM_MUTATION- renvoie{ success, message, submissionId, ... }.
Celles-ci, à vous de les écrire
Elles n'ont pas de helper SDK. Envoyez-les via client.queryScoped(...).
Enregistrements de modèles personnalisés
query PublicModelRecords(
$workspaceId: String!
$modelSlug: String!
$filter: JSON
$sort: String
$limit: Int
$offset: Int
$populate: [String!]
) {
public {
model {
records(
workspaceId: $workspaceId
modelSlug: $modelSlug
filter: $filter
sort: $sort
limit: $limit
offset: $offset
populate: $populate
) {
items { id modelId data status createdAt updatedAt }
total
hasMore
}
}
}
}Écrivez la requête vous-même et gardez-la dans votre dépôt. Le SDK contient bien des chaînes équivalentes, mais sous @cmssy/core/internal - un sous-chemin interne, qui peut donc changer d'une version à l'autre sans mention de rupture. Votre propre requête tient en quatre lignes et ne vous surprendra jamais.
Lister les pages enfants
C'est ce qui alimente un index de blog ou une arborescence de documentation :
query PublicPagesByType(
$workspaceId: String!
$parentSlug: String
$search: String
$limit: Int
$offset: Int
) {
publicPagesByType(
workspaceId: $workspaceId
parentSlug: $parentSlug
search: $search
limit: $limit
offset: $offset
) {
items {
id
slug
fullSlug
publishedAt
displayName
seoTitle
seoDescription
customFields
pageType
}
total
hasMore
}
}Soumettre un formulaire
mutation SubmitForm($formId: ID!, $input: SubmitFormInput!) {
public {
form {
submit(formId: $formId, input: $input) {
success
message
submissionId
redirectUrl
}
}
}
}Exportée sous le nom SUBMIT_FORM_MUTATION. Passez { formId, input: { data } }.
Auth des membres : ne pas appeler directement
Les mutations siteMember - login, register, refresh, logout, forgotPassword, resetPassword, verifyEmail - portent le flux d'authentification des membres.
Ne les appelez pas depuis votre propre code. Montez plutôt createCmssyAuthRoute : il les gère côté serveur et scelle le cookie de session. Les appeler directement revient à gérer vous-même le scellement des jetons, et s'y tromper est une faille de sécurité, pas une page cassée.
Bon à savoir
dataetfilterutilisent le scalaireJSON- passez des objets simples, pas du JSON en chaîne.customFieldssur une page est une mapJSONdes champs personnalisés de son type de page.- Les lectures ne renvoient que du contenu publié, sauf si un
previewSecretvalide est fourni. Le SDK s'en charge en mode édition avec votredraftSecret.
Étapes suivantes
- Serveur MCP - le chemin d'écriture.
- Loaders serveur - là où vivent généralement les requêtes personnalisées.
- Authentification des membres - le flux derrière les mutations
siteMember.