Úvod do GraphQL na Replit (část 1)

V tomto projektu vytvoříme web, který načte data z koncového bodu GraphQL. Koncový bod odhaluje data související s imaginárním podcastem s názvem GraphQL FM .

Na konečný projekt se můžete podívat na https://repl.it/@ritza/GraphQL-FM. Můžete ji také zobrazit jako samostatnou stránku stisknutím Open in a new tab (v pravé horní části předchozího odkazu) nebo přímo na https://graphql-fm.ritza.repl.co.

Výše uvedený příklad vytvoříme ve dvou samostatných krocích. Část 1 (tento článek) pokrývá základy GraphQL a nastavení našeho API. Část 2 ukáže, jak můžeme data z GraphQL API přeměnit na plně funkční web. Začneme s následujícím:

  • Vytvoření vlastního projektu pomocí Replit
  • Naše cíle GraphQL pro tuto příručku
    • Co je GraphQL?
    • GraphQL jako alternativa k REST
    • „Ahoj světe“ v GraphQL
    • Použití Průzkumníka GraphQL
  • Vytvoření rozhraní API
    • GraphQL jako služba
    • Přidání GraphQL do JavaScriptu
    • Vlastní funkce GraphQL
    • Definování informační architektury
    • Načítání dat

Vytvoření vlastního projektu pomocí Replit

Pokud jste to ještě neudělali, přejděte na stránku registrace a vytvořte si účet Replit. Po vytvoření nastavte nový projekt:

  1. Kliknutím na + New repl tlačítko.
  2. Výběr jazyka „HTML, CSS, JS“.
  3. Pojmenování vaší odpovědi:V našem případě „graphql-fm“.
  4. Kliknutím na Create repl tlačítko.

Protože jsme jako jazyk vybrali „HTML, CSS, JS“, Replit vytvořil základní soubory potřebné pro náš front-endový projekt, který by měl být:

  • index.html
  • style.css
  • script.js

Naše cíle GraphQL pro tuto příručku

Naším cílem je:

  • Seznamte se s konceptem GraphQL.
  • Ukažte, jak můžeme použít GraphQL v nativním kódu JavaScript, aniž bychom potřebovali další knihovny nebo rámce.

To znamená, že i když jste již s GraphQL obeznámeni, ale zažili jste jej pouze prostřednictvím knihoven jako Apollo nebo Relay, zjistíte, že se naučíte používat GraphQL pomocí nativního JavaScript Fetch API.

Co je GraphQL?

Možná jste viděli definice GraphQL, které vypadají takto:

Pojďme se podívat, co to vlastně znamená. Konkrétně „domain-specific language“ (DSL) je programovací jazyk vytvořený k vyjádření velmi specifického a úzkého typu digitální informace (domény). Zatímco obecný jazyk, jako je JavaScript, lze použít k vyjádření široké škály digitálních informací, jazyky specifické pro doménu bývají omezenější. Je to však právě kvůli jejich úzkému rozsahu, že DSL lze snáze číst a zapisovat ve srovnání s univerzálními jazyky.

Kvůli tomuto omezenému rozsahu jsou DSL často zabudovány do jiných jazyků, protože často potřebují využít větší funkčnost poskytovanou univerzálními jazyky. To však neznamená, že DSL jsou vázány na konkrétní jazyky. Například SQL (Structured Query Language) je další jazyk specifický pro doménu, který se používá k dotazování databázových struktur, jako je MySQL nebo Postgres. Přesto má SQL stejnou přesnou syntaxi, ať už je vložená do JavaScriptu, Pythonu nebo PHP.

Například v JavaScriptu (prostřednictvím Node) můžete provést následující:

const { createConnection } = require('mysql');

const connection = createConnection({
  host: "localhost",
  user: "yourusername",
  password: "yourpassword",
  database: "mydb"
});

connection.query("SELECT * FROM customers");

Zatímco v Pythonu můžete udělat toto:

import mysql.connector

db = mysql.connector.connect(
  host="localhost",
  user="yourusername",
  password="yourpassword",
  database="mydatabase"
)

db.cursor().execute("SELECT * FROM customers")

Všimněte si, že výraz SQL (SELECT * FROM customers ) je úplně stejný bez ohledu na prostředí. Podobně nám GraphQL umožňuje vyjádřit konkrétní datové dotazy nezávisle na tom, jak (nebo kde) je používáme.

GraphQL jako alternativa k REST

GraphQL lze použít k vyjádření téměř jakéhokoli typu požadavku na data. Jako příklad, nesmírně populární framework Gatsby React používá GraphQL k dotazování frontmatu a prostého textu v souborech Markdown. Ve většině případů se však GraphQL používá jako alternativa k tradičnímu přístupu REST (Representational State Transfer).

REST byl dlouhou dobu považován za de-facto standard pro odesílání dat mezi prohlížečem a serverem. Jeho obliba pramení z široké škály standardizovaných operací, které umožňuje. Ty zahrnují přijímání dat (GET), odesílání dat (POST), slučování dvou datových struktur (PATCH) nebo dokonce odstraňování dat (DELETE). Primární nevýhodou REST je však to, že se spoléhá na vytváření pevných datových koncových bodů. To znamená, že jeden požadavek je omezen pouze na konkrétní, předem definovanou sadu dat. Chimezie Enyinnaya, nigerijský tvůrce obsahu pro Pusher (službu, která spravuje vzdálené zasílání zpráv v hospodách/podřízených), to vysvětluje následovně:

GraphQL byl vytvořen jako řešení tohoto problému. Facebook jej vytvořil, aby poskytoval standardizovanou syntaxi pro psaní výraznějších (a výkonnějších) datových dotazů v rámci mobilní aplikace Facebook při načítání vzdálených dat.

"Ahoj světe" v GraphQL

Kde tedy začít s GraphQL?

Existuje několik knihoven GraphQL, které poskytují užitečné abstrakce při práci s GraphQL. Nejoblíbenější jsou Apollo a Relay. I když poskytují mnoho užitečných funkcí, jako je správa mezipaměti a normalizace, mohou být pro někoho, kdo s GraphQL teprve začíná, ohromující. Bývají také poměrně velcí a domýšliví – což znamená, že pro menší, flexibilnější projekty mohou být přehnaní.

GrahpQL je otevřený standard (podobný HTML). Není proto uzamčen na žádný konkrétní nástroj, knihovnu nebo platformu. To znamená, že jsme schopni používat GraphQL přímo s nativním JavaScript fetch API, nebo dokonce s lehkou knihovnou AJAX, jako je Axios. V níže uvedeném příkladu zjistíme, jaký by byl ekvivalent GraphQL v JavaScriptu „Hello World“. Jinými slovy:

Použití Průzkumníka GraphQL

Většina koncových bodů GraphQL přichází s nějakou formou průzkumníka GraphQL, nejoblíbenější je GraphiQL a GraphQL Playground. Jako příklad začněme s veřejným koncovým bodem GraphQL poskytovaným platformou pro správu událostí Universe.com. Jejich koncový bod umožňuje vývojářům získávat data spojená s konkrétními událostmi v jejich databázi. Můžeme použít jejich průzkumníka k vytvoření a testování super základního dotazu.

Pokud přejdete na https://universe.com/graphiql, měli byste vidět následující:

Levé (bílé) podokno umožňuje psát konkrétní dotazy, zatímco prostřední (šedé) podokno zobrazuje odpověď z koncového bodu po spuštění dotazu. Konečně pravý (bílý) panel obsahuje dokumentaci vygenerovanou koncovým bodem (pokud je skrytý, klikněte na pravé horní tlačítko s nápisem „ "). Tlačítko Přehrát (postranní trojúhelník v levém horním rohu) provede aktuální dotaz, zatímco "Prettify" přeformátuje váš dotaz podle osvědčených postupů (pokud jde o rozvržení). "Historie" umožňuje zobrazit dotazy použité dříve v průzkumníka.

Můžeme spustit výchozí počáteční dotaz (v době psaní článku) a dostaneme odpověď podobnou JSON, která vypadá asi takto:

{
  "data": {
    "event": {
      "title": "End of Unix Time",
      "address": "Los Angeles, CA, USA",
      "currency": "USD",
      "host": {
        "firstName": "Joshua"
      },
      "timeSlots": {
        "totalCount": 2,
        "nodes": [
          {
            "startAt": "2018-08-31T12:00:00"
          },
          {
            "startAt": "2038-01-18T21:00:00"
          }
        ]
      }
    }
  }
}

Pojďme se podívat na to, co se právě stalo. Vymažeme levé podokno a krok za krokem znovu vytvoříme dotaz.

Můžeme začít přidáním query { } . To znamená pro koncový bod, že chceme načíst data ze serveru.

Umístěte kurzor do složených závorek a současně stiskněte mezerník a klávesy Enter. Měli bychom získat seznam doporučených dotazů (na základě struktury dat) takto:

Podle našeho původního příkladu znovu vyberte event . To znamená, že chceme získat informace spojené s konkrétní událostí. Událost, která nás zajímá, má jedinečné ID 5879ad8f6672e70036d58ba5 . Toto ID můžeme předat jako argument dotazu (podobně jako u funkcí JavaScriptu) takto:event(id: "5879ad8f6672e70036d58ba5") { } .

Nyní, když jsme identifikovali událost, na kterou se chceme dotazovat, můžeme dát GraphQL pokyn, aby načetl pouze informace, které nás zajímají. To zabrání tomu, aby odpověď vrátila celou datovou strukturu události (tzv. over-fetching v REST). . Abychom ilustrovali dynamickou povahu GraphQL, budeme se dotazovat na úplně jiná data spojená s událostí, jak je ukázáno v příkladu níže:

query {
  event(id: "5879ad8f6672e70036d58ba5") {
    active
    address
    url
  }
}

Všimněte si, že náš první příklad měl vnořené dotazy . Zde se stává ústředním rozdíl mezi GraphQL a REST. Vše, co jsme až do tohoto okamžiku udělali, se velmi drží způsobu, jakým bychom uvažovali o tradičním požadavku REST.

Funkce požadavků REST je podobná tradiční funkci JavaScriptu, kde poskytujeme konkrétní argumenty a na základě argumentů dostáváme předem stanovenou odpověď. GraphQL funguje trochu jinak. Dotazy GraphQL jsou jako malé mapy používané k navigaci a vyhledání všech požadovaných dat během jedné cesty. To znamená, že můžeme konceptualizovat sadu instrukcí z reálného světa pomocí syntaxe GraphQL takto:

instructions {
  travel(type: "drive") {
    mall {
      travel(type: "walk") {
        general_store {
          food_isle {
            bread
            peanut_butter
          }
          stationary_isle {
            pens (amount: 12)
            paper
          }
        }
        hardware_store {
          nails
          hammer
        }
      }
    }
    post_office {
      packages
      mail
    }
  }
}

Vzhledem k tomu, že GraphQL je struktura podobná grafu, můžeme získat informace volně související s naší událostí, aniž bychom museli vytvářet zcela nový požadavek. To je místo, kde GraphQL skutečně září ve srovnání s REST! Můžete si je představit jako silnice nebo stezky spojující různá místa. Jinými slovy, pokud jste v obchodním centru (jako v našem příkladu výše), můžete přejít přímo na general_store_store v tom mall a poté na hardware_store později. Navíc, protože mall je připojen k post_office po silnici, můžete jet na post_office poté.

Díky mapové povaze dotazů můžeme mít dotaz, který sleduje kruhovou trasu a končí přesně tam, kde začal (neexistuje pro to žádný skutečný praktický důvod, ale demonstruje to grafové základy GraphQL).

query {
  event(id: "5879ad8f6672e70036d58ba5") {
    active
    address
    url

    timeSlots {
      nodes {
        event {
          active
          address
          url
        }
      }
    }
  }
}

Vytvoření rozhraní API

Gratulujeme, nyní můžete psát základní dotazy GraphQL!

Dále budeme chtít vytvořit vlastní koncový bod, protože omezení na data z Universe.com je limitující. Existuje několik serverových rámců GraphQL. Některé extrémně populární příklady jsou express-graphql pro Node (běžící Express) a Graphene pro Python servery. Alternativně existuje několik řešení typu vše v jednom, jako je Prisma nebo Hasura, která jsou dodávána s databázemi.

GraphQL jako služba

Pro zjednodušení budeme používat platformu svobodného softwaru jako služby (SaaS) s názvem GraphCMS. To nám umožňuje získat vlastní koncový bod GraphQL s minimálním nastavením.

Chcete-li pokračovat:

  1. Navštivte https://graphcms.com a zaregistrujte si bezplatný účet.
  2. Jakmile bude váš účet vytvořen, vytvořte nový ukázkový projekt výběrem šablony „Podcast Starter“.
  3. Ujistěte se, že je vybrána možnost „Zahrnout obsah šablony“, protože to vyplní naše rozhraní API zástupnými informacemi.
  4. Přidávejte nebo upravujte obsah do rozhraní API pomocí řídicího panelu projektu GraphCMS, ale ujistěte se, že neměníte schéma, protože na něj budeme při psaní našich dotazů spoléhat.

Všimněte si, že GraphCMS vám umožňuje vytvořit nový projekt úplně od začátku, ale pro naše účely chceme mít pouze funkční koncový bod se zástupným obsahem. Pokud máte zájem ponořit se hlouběji do GraphCMS, můžete se podívat na jejich dokumentaci na https://graphcms.com/docs.

Po vytvoření projektu můžete vybrat „Nastavení“ v levém dolním rohu a přejděte na „Přístup k rozhraní API“. Nezapomeňte zkopírovat adresu URL koncového bodu (v horní části stránky) a uložit ji někam, kde k ní budete mít později přístup. Všechny naše dotazy GraphQL budeme směřovat na tuto adresu URL, takže je užitečné ji mít po ruce.

Všimněte si, že váš koncový bod API by měl vypadat nějak takto:

https://api-us-east-1.graphcms.com/v2/ckll20qnkffe101xr8m2a7m2h/master

V dalších příkladech kódu však použijeme <<<YOUR ENDPOINT HERE>>> abyste zabránili náhodnému použití příkladu koncového bodu, pokud budete následovat. Pokud ve svém prohlížeči přejdete přímo ke svému koncovému bodu, zobrazí se vám Průzkumník GraphiQL, který vám umožní testovat a zkoušet dotazy pro váš konkrétní koncový bod:

Přidání GraphQL do JavaScriptu

Vezměme dotaz vytvořený v našem průzkumníkovi koncového bodu API GraphiQL a umístěte jej do našeho souboru JavaScript. To nám umožňuje požadovat výše uvedená data přímo z našeho prohlížeče:

Všimněte si, že následující příklad předpokládá znalost nativního rozhraní JavaScript Fetch API. Pokud se s tím setkáváte poprvé, přečtěte si, jak používat JavaScript Fetch API k získávání dat.

const QUERY = `
  query {
    episodes {
      title
    }
  }
`

const FETCH_OPTIONS =   {
  method: 'POST',
  body: JSON.stringify({ query: QUERY }),
}

fetch('<<<YOUR ENDPOINT HERE>>>', FETCH_OPTIONS )
  .then(response => response.json())
  .then(console.log)

Výše uvedené by mělo do konzole prohlížeče odeslat něco následujícího:

{
  "data": {
    "episodes": [
      {
        "title": "# Cras eu urna at ligula – tempus commodo"
      },
      {
        "title": "# Phasellus feugiat – non massa eu tincidunt"
      },
      {
        "title": "# Lorem ipsum dolor sit"
      }
    ]
  }
}

Vlastní funkce GraphQL

Z našich webových stránek položíme několik dotazů GraphQL. Pro tento účel je užitečné vytvořit základní abstrakci (pomocí funkce JavaScript), která tyto požadavky zpracovává, aby se omezil standardní kód. Náš příklad JavaScriptu výše můžeme převést na základní funkci JavaScriptu následovně:

Všimněte si, že následující část předpokládá znalost operátorů async/await v JavaScriptu. Pokud je neznáte, podívejte se na následující příručku na Mozilla Developer Network.

const gqlQuery = async (query) => {
  const REQUEST_OPTIONS = { method: 'POST', body: JSON.stringify({ query }) };

  const response = await fetch('<<<YOUR ENDPOINT HERE>>>', REQUEST_OPTIONS)

  if (!response || !response.ok) {
    throw new Error('Query failed');
  }

  const { data } = await response.json();
  return data;
}

To nám umožňuje předat dotaz funkci, která na oplátku poskytne odpověď, jakmile se dotaz vyřeší. Zahrnujeme také funkci check-in, abychom zjistili, zda byla odpověď úspěšná (kontrolou, zda vrátila 200 stav pomocí response.ok ).

To znamená, že bychom měli být schopni udělat následující:

const QUERY = `
  query {
    episodes {
      title
    }
  }
`

gqlQuery(QUERY).then(console.log)

To funguje, ale vždy vrátí pole všech epizody z celé naší databáze. Pokud chceme pouze dvě nejnovější epizody, můžeme v našem dotazu provést následující:

query {
  episodes(first: 2) {
    title
  }
}

To však není příliš flexibilní, protože to znamená, že pokaždé, když chceme získat konkrétní počet epizod, budeme muset vytvořit celý nový dotaz. Naštěstí nám GraphQL umožňuje předat proměnné jako součást dotazu. Pokud se například podíváme do našeho Průzkumníka GraphiQL, můžeme provést následující (možná budete muset kliknout na „PROMĚNNÉ DOTAZU“ v levém dolním rohu, abyste jej otevřeli):

Uvidíte, že můžeme předat proměnné jako objekt JSON, a pak v rámci dotazu můžeme deklarovat očekávané proměnné v hranatých závorkách (( ) ) hned za query příkaz. Názvy proměnných by měly vždy začínat znakem dolaru ($ ). V našem případě můžeme zadat, že očekáváme $count . Protože je však GraphQL silně typizovaný jazyk, musíme deklarovat, jaký typ dat $count bude. V tomto případě to bude Int hodnota. Poté předáme hodnotu $count přímo na episodes(first: $count) . Abychom to replikovali v našem JavaScriptu, můžeme do našeho těla přidat proměnné takto:

Pokud neznáte koncept silně zadávaných jazyků, přečtěte si následujícího průvodce od Glavia Copese.

const gqlQuery = async (query, variables) => {
  const REQUEST_OPTIONS = { method: 'POST', body: JSON.stringify({ query, variables }) };

  const response = await fetch('<<<YOUR ENDPOINT HERE>>>', REQUEST_OPTIONS)

  if (!response || !response.ok) {
    throw new Error('Query failed');
  }

  const { data } = await response.json();
  return data;
}

To znamená, že budeme moci provést následující (což přihlásí první, první dvě a první tři epizody do konzole):

const QUERY = `
  query ($count: Int) {
    episodes(first: $count) {
      title
    }
  }
`

gqlQuery(QUERY, { count: 1 }).then(console.log)
gqlQuery(QUERY, { count: 2 }).then(console.log)
gqlQuery(QUERY, { count: 3 }).then(console.log)

Definování informační architektury

Když je náš koncový bod nyní nastavený, musíme začít mapovat všechny informace, které chceme na každé stránce zobrazit. Ve světě uživatelské zkušenosti tomu říkáme mapování informační architektury.

Jako příklad uvažujme následující základní osnovu, kterou použijeme jako referenci při vyžádání dat z koncového bodu:

# GraphQL FM Website

## Episodes Page (Default Landing Page)

- The first episode (for hero banner)
  - Unique ID (This will be used as the URL when viewing the episode)
  - Episode name
  - Cover image URL
  - Audio
    - File URL
    - File type (for example `.mp3`, `.wav`, etc.)

- Previous episodes (all episodes after the first one)
  - Unique ID (This will be used as the URL when viewing the episode)
  - Published date
  - Episode name
  - Cover image URL

## Single Episode Page

- Previous episode ID (if applicable)
- Next episode ID (if applicable)

  - Current episode
  - Episode number
  - Published date
  - Episode name
  - Cover image URL
  - Show notes
  - List of topics associated with episode
  - Audio
    - File URL
    - File type (for example `.mp3`, `.wav`, etc.)
  - List of guests
    - Name of each guest
    - Photo URL of each guest
  - List of episode sponsors
    - Name of sponsoring  company
    - Website URL of sponsoring company

## Guests Page

- List of guests
  - Name of each guest
  - Photo URL of each guest
  - List of episodes that appeared on
    - Unique ID (This will be used as the URL when viewing the episode)
    - Date that each episode was published
    - Episode name for each episode
    - Cover image URL for each episode

## Topics Page

  - A list of all topics
    - The name of each topic
    - All episodes associated with a specific topic
      - Unique ID if the episode (This will be used as the URL when viewing the episode)
      - The date that each episode was published
      - The name of each episode
      - The cover image URL of each episode

## Resources Page

  - A list of all resources
    - The filename of each individual resource
    - The file type (for example `.mp3`, `.wav`, etc.) of each resource
    - The URL where each individual resource can be downloaded

## Sponsors Page

  - A list of all sponsors
    - The company name associated with each sponsorship
    - All the episodes that a specific company is sponsoring
      - Unique ID if the episode (This will be used as the URL when viewing the episode)
      - The date that each episode was published
      - The name of each episode
      - The cover image URL of each episode

Načítání dat

Při vytváření naší informační architektury okamžitě vynikne jedna věc:existují určité specifické datové kokonfigurace, které jsou volány vícekrát. Naštěstí standardizace GraphQL umožňuje něco, čemu se říká fragmenty. Fragments pomáhá udržovat naše dotazy SUCHÉ (programátorská zkratka pro Don't Repeat Yourself). Zdá se, že nejběžnější spolukonfigurací jsou data potřebná k zobrazení náhledu konkrétní epizody.

Můžeme to zabalit do fragmentu GraphQL následovně (velmi podobné tomu, jak bychom vytvořili samotný dotaz v JavaScriptu):

const EPISODE_PREVIEW_FRAGMENT = `
  fragment EpisodePreview on Episode {
    id
    date: publishedAt
    title
    image {
      url
    }
  }
`

Poté jej můžeme použít v konkrétním dotazu následovně (pomocí interpolace řetězců JavaScript):

const GUESTS_PAGE_QUERY = `
  query {
   peoples {
    fullName
    photo {
      url
    }
    episodes: appearedOn {
      ...EpisodePreview
    }
  }
 }

  ${EPISODE_PREVIEW_FRAGMENT}

Je běžnou praxí umístit fragmenty za dotazovací výraz místo jejich deklarování před dotazem, protože dotaz by měl být především expresivní. Jako odkaz bychom měli spíše zahrnout fragmenty jako poznámky pod čarou. Pomocí naší informační architektury a fragmentu deklarovaného výše můžeme nahradit veškerý obsah v našem souboru JavaScript následujícím:

const EPISODE_PREVIEW_FRAGMENT = `
  fragment EpisodePreview on Episode {
      id
      date: publishedAt
      title
      image {
        url
      }
  }
`

const EPISODES_PAGE_QUERY = `
    query {
    first: episodes(first: 1) {
      id
      title
      image {
        url
      }
      audio: audioFile {
        url
        mime: mimeType
      }
    }

    previous: episodes(skip: 1) {
      ...EpisodePreview,
    }
  }

  ${EPISODE_PREVIEW_FRAGMENT}
`;

const SINGLE_EPISODE_PAGE_QUERY = `
  query($id: ID) {
    episode(where: { id: $id }) {
      number: episodeNumber
      date: publishedAt
      title
      description
      notes: showNotes
      audio: audioFile {
        url
        mime: mimeType
      }
      image {
        url
      }
      guests {
        fullName
        photo {
          url
        }
      }
      tags {
        name
      }
      sponsors {
        company {
          name
          website
        }
      }
    }
  }
`;

const SINGLE_EPISODE_NEIGHBORS_QUERY = `
  query($previous: Int, $next: Int) {
    previous: episode(where: { episodeNumber: $previous }) { id }
    next: episode(where: { episodeNumber: $next }) { id }
  }
`;

const GUESTS_PAGE_QUERY = `
  query {
   peoples {
    fullName
    photo {
      url
    }
    episodes: appearedOn {
      ...EpisodePreview
    }
  }
 }

 ${EPISODE_PREVIEW_FRAGMENT}
`;

const TOPICS_PAGE_QUERY = `
  query {
    tags {
      name
      episodes {
        ...EpisodePreview
      }
    }
  }

  ${EPISODE_PREVIEW_FRAGMENT}
`;

const RESOURCES_PAGE_QUERY = `
  query {
     assets {
      fileName
      mimeType
      url
    }
  }

  ${EPISODE_PREVIEW_FRAGMENT}
`;

const SPONSORS_PAGE_QUERY = `
  query {
    sponsorships {
      company {
        name
      }
      episodes {
        ...EpisodePreview
      }
    }
  }

  ${EPISODE_PREVIEW_FRAGMENT}
`;

const gqlQuery = async (query, variables) => {
  const response = await fetch(
    "https://api-us-east-1.graphcms.com/v2/ckll20qnkffe101xr8m2a7m2h/master",
    {
      method: "POST",
      body: JSON.stringify({ query, variables })
    }
  );

  if (!response || !response.ok) {
    throw new Error("Query failed");
  }

  const { data } = await response.json()
  return data;
};

const getData = async () => {
  const episodes = await gqlQuery(EPISODES_PAGE_QUERY);
  const guests = await gqlQuery(GUESTS_PAGE_QUERY);
  const topics = await gqlQuery(TOPICS_PAGE_QUERY)
  const sponsors = await gqlQuery(SPONSORS_PAGE_QUERY)

  const [{ id }] = episodes.first;
  const singleEpisode = await gqlQuery(SINGLE_EPISODE_PAGE_QUERY, { id });

  const { number } = singleEpisode.episode;

  const singleEpisodeNeighbhors = await gqlQuery(
    SINGLE_EPISODE_NEIGHBORS_QUERY,
    { previous: number + 1, next: number - 1 }
  )

  console.log({
    episodes,
    guests,
    topics,
    sponsors,
    singleEpisode,
    singleEpisodeNeighbhors,
  });
};

getData();

Pokud spustíte výše uvedené, získáte v konzoli prohlížeče jeden velký objekt. Tento objekt obsahuje všechna data, která budeme používat na našem webu:

Mít data v konzoli prohlížeče nestačí. Potřebujeme udělat další práci, abychom jej strukturovali do HTML a CSS, aby jej mohli přímo konzumovat uživatelé. V části 2 si to projdeme a přeměníme naše data na plně funkční web.