Teraz z AI - twórz strony przez serwer MCP

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}/graphql

apiBase 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łaj client.queryScoped(...): gdy Twoje zapytanie deklaruje $workspaceId, a Ty go nie podasz, SDK rozwiąże je z workspaceSlug i wstrzyknąć zarówno zmienną, jak i nagłówek x-workspace-id.
// $workspaceId zostaje uzupełnione za Ciebie
await client.queryScoped(MY_QUERY, { modelSlug: "products", limit: 20 });

Co SDK już opakowuje

Normalnie nigdy tego nie piszesz - wymieniony helper wywołuje to za Ciebie.

  • publicPagefetchPage - zwraca { id, blocks, publishedBlocks }.
  • publicPageByIdfetchPageById - zwraca { id, publishedBlocks }.
  • publicPagesfetchPages - zwraca [{ id, slug, updatedAt, publishedAt }].
  • publicPage (pola SEO) → fetchPageMeta - zwraca { id, seoTitle, seoDescription, seoKeywords, displayName }.
  • publicPageLayoutsfetchLayouts - zwraca [{ position, blocks }].
  • publicSiteConfigfetchSiteConfig / resolveSiteLocales - nazwa serwisu, locale, funkcje, branding.
  • public.form.getresolveForms (oraz context.forms) - pola i ustawienia formularza.
  • public.form.submitSUBMIT_FORM_MUTATION - zwraca { success, message, submissionId, ... }.

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
) {
  publicPagesByType(
    workspaceId: $workspaceId
    parentSlug: $parentSlug
    search: $search
    limit: $limit
    offset: $offset
  ) {
    items {
      id
      slug
      fullSlug
      publishedAt
      displayName
      seoTitle
      seoDescription
      customFields
      pageType
    }
    total
    hasMore
  }
}

Wysłanie formularza

mutation SubmitForm($formId: ID!, $input: SubmitFormInput!) {
  public {
    form {
      submit(formId: $formId, input: $input) {
        success
        message
        submissionId
        redirectUrl
      }
    }
  }
}

Eksportowane jako SUBMIT_FORM_MUTATION. Przekaż { formId, input: { data } }.

Autoryzacja członków: nie wywołuj bezpośrednio

Mutacje siteMember - login, register, refresh, logout, forgotPassword, resetPassword, verifyEmail - stoją za przepływem logowania członków.

Nie wywołuj ich z własnego kodu. Zamiast tego zamontuj createCmssyAuthRoute: obsługuje je po stronie serwera i pieczętuje ciasteczko sesji. Wywoływanie ich wprost oznacza, że sam ogarniasz pieczętowanie tokenów, a pomyłka tutaj to błąd bezpieczeństwa, nie zepsuta strona.

Warto wiedzieć

  • data i filter używają skalara JSON - przekazuj zwykłe obiekty, nie JSON jako string.
  • customFields na stronie to mapa JSON pó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 Twojego draftSecret.

Następne kroki