API dostawcze GraphQL
Jakie zapytania istnieją, jak działa scoping workspace'u i które odczyty opakowuje SDK, a które piszesz sam.
cmssy serwuje opublikowaną treść przez jeden endpoint GraphQL. SDK opakowuje już typowe odczyty - strony, layouty, konfigurację serwisu, formularze - więc większość aplikacji nigdy nie pisze zapytania. Do reszty (własne modele, rekordy, listowanie stron potomnych) wysyłasz własne przez klienta dostawczego.
Endpoint i scoping
Publiczne odczyty idą na ścieżkę z organizacją:
{apiBase}/public/{orgSlug}/{workspaceSlug}/graphqlapiBase to Twoje apiUrl z obciętym końcowym /graphql - domyślnie https://api.cmssy.io, więc żądania lądują na https://api.cmssy.io/public/{org}/{ws}/graphql. Nadpisuj apiUrl tylko przy self-hoście. org i workspaceSlug pochodzą z Twojej konfiguracji, a SDK składa ścieżkę za Ciebie.
Ponieważ organizacja siedzi w ścieżce, slug workspace'u musi być unikalny tylko w obrębie swojej organizacji.
Dwa sposoby ograniczenia zapytania
Każda operacja jest ograniczona do workspace'u, ale nie wszystkie tak samo. To ten szczegół, na którym ludzie się wykładają:
workspaceSlug(String!) - używany przez odczyty stron, layoutów, konfiguracji i formularzy. Helpery SDK podają go automatycznie z Twojej konfiguracji.workspaceId(String!) - używany przez odczyty modeli, rekordów i stron po typie. Wywołajclient.queryScoped(...): gdy Twoje zapytanie deklaruje$workspaceId, a Ty go nie podasz, SDK rozwiąże je zworkspaceSlugi wstrzyknąć zarówno zmienną, jak i nagłówekx-workspace-id.
// $workspaceId zostaje uzupełnione za Ciebie
await client.queryScoped(MY_QUERY, { modelSlug: "products", limit: 20 });Co SDK czyta za Ciebie
Normalnie nigdy tego nie piszesz - createCmssyPage, CmssyServerLayout i rozwiązywanie formularzy stojące za context.forms wysyłają te zapytania wewnętrznie.
public.page.get- jedna strona po slugu:{ id, blocks, publishedBlocks }plus pola SEOseoTitle,seoDescription,seoKeywords,displayName.public.page.getById-{ id, publishedBlocks }.public.page.list-[{ id, slug, updatedAt, publishedAt }].public.page.layouts-[{ position, blocks, settings }].public.siteConfig- nazwa serwisu, język domyślny i włączone języki, funkcje, branding.public.form.get- pola i ustawienia formularza, podawane blokom jakocontext.forms.public.form.submit-{ success, message, submissionId, redirectUrl }.
Helpery, które je opakowują - fetchPage, fetchPages, fetchLayouts, fetchPageMeta, fetchSiteConfig, resolveSiteLocales, resolveForms - żyją pod @cmssy/core/internal i nie są publicznym API. Publiczna powierzchnia to createCmssyClient i graphqlRequest: czegokolwiek createCmssyPage już nie wyrenderuje, pytasz sam.
Te napiszesz sam
Nie mają helpera w SDK. Wyślij je przez client.queryScoped(...).
Rekordy własnych modeli
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
}
}
}
}Napisz zapytanie sam i trzymaj je w swoim repo. SDK ma odpowiedniki tych stringów, ale pod @cmssy/core/internal - to podscieżka wewnętrzna, co znaczy, że może się zmienić między wydaniami bez adnotacji o breaking change. Twoje własne zapytanie ma cztery linijki i nigdy Cię nie zaskoczy.
Listowanie stron potomnych
To jest to, co napędza indeks bloga albo drzewo docsów:
query PublicPagesByType(
$workspaceId: String!
$parentSlug: String
$search: String
$limit: Int
$offset: Int
) {
public {
page {
byType(
workspaceId: $workspaceId
parentSlug: $parentSlug
search: $search
limit: $limit
offset: $offset
) {
items {
id
slug
fullSlug
publishedAt
displayName
seoTitle
seoDescription
customFields
pageType
}
total
hasMore
}
}
}
}byType przyjmuje też pageType, sortBy i customFieldFilters, a przy prawidłowym previewSecret - includeDrafts.
Wysłanie formularza
mutation SubmitForm($formId: ID!, $input: SubmitFormInput!) {
public {
form {
submit(formId: $formId, input: $input) {
success
message
submissionId
redirectUrl
}
}
}
}Przekaż { formId, input: { data } }. SDK niesie ten sam string jako SUBMIT_FORM_MUTATION, ale pod @cmssy/core/internal - trzymaj własną kopię, zamiast go importować.
Autoryzację członków montujesz sam
Mutacje siteMember - login, register, refresh, logout, forgotPassword, resetPassword, verifyEmail - stoją za przepływem logowania członków.
Slim SDK nie dostarcza ani trasy auth, ani czytnika sesji. login i refresh zwracają surowe accessToken i refreshToken, a backend nie ustawia żadnego ciasteczka - sesja należy do Twojej aplikacji. Bezpieczny domyślny wybór to ciasteczko httpOnly zapisywane przez Twój własny route handler. Cały przepływ, od rejestracji po weryfikację e-maila, opisuje autoryzacja członków.
Warto wiedzieć
dataifilterużywają skalaraJSON- przekazuj zwykłe obiekty, nie JSON jako string.customFieldsna stronie to mapaJSONpól własnych danego typu strony.- Odczyty zwracają wyłącznie treść opublikowaną, chyba że podano prawidłowy
previewSecret. SDK robi to za Ciebie w trybie edycji, używając TwojegodraftSecret.
Następne kroki
- Serwer MCP - ścieżka zapisu.
- Loadery serwerowe - tam zwykle żyją własne zapytania.
- Autoryzacja członków - przepływ stojący za mutacjami
siteMember.