Crea una cuenta o inicia sesión

¡Continúa aprendiendo sin ningún costo! Únete y comienza a potenciar tu carrera

Convierte tus certificados en títulos universitarios en USA

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

16 Días
22 Hrs
18 Min
28 Seg

Scalars, filtros y queries avanzadas

4/23
Recursos

Aportes 18

Preguntas 7

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Al ver un curso espero aprender cosas no a escuchar explicaciones de codigos y/o proyectos que ya estan todos desarrollados… Cual seria el objetivo de este curso si solo me pongo a leer codigo
Para otros cursos mejor ponte a programar desde cero y explicar, no te pongas a explicar codigo que ya esta escrito 😃

Me gusta mucho la metodología para enseñar que usa este profesor.
Es dificil, pero genera un gran reto en cada clase

Me perdonaran pero que sentido tiene venir a una clase a leer el 30% del total del código agregado y ver al profesor copiar y pegar, no es que no quiera tomarme el tiempo de entender pero se trata de una clase

Por si alguien se pregunta de dónde sacó el profesor la definición del scalar (al menos yo no la sabía, ni la entendía), la tomó de esta documentación de Apollo, creo que esta otra docu de GraphQL también les resultará útil.

Después de 3 días aprendiendo TypeScript corregí mi código basado en esta clase 😄 😄
Lo explicare paso a paso:


  • Dividí el código en una carpeta models la cual tiene el archivo schema.graphql y una resolvers con los resolvers.

  • El index.ts configure el context del apollo server para pasar la “db” (luego tendra sentido)

  • El schema.graphql tiene el modelo de la clase:

  • Dentro de resolvers/index.ts cree el objeto para el resolver de apollo server

  • Para configurar los queries y mutations cree sus propios archivos y el objeto context tiene toda la información de la “db” que configure en la propiedad context del apollo server (ignoren el type de la línea 3 xd)

  • Dentro de /resolvers/base estan algunos tipos usados en los queries y mutations y el resolver para el type Avocado o algún otro type si llegara a crear otro

El unico problema que tuve fue este warning:

Fue muy complejo pero divertido programar todo eso, aprendi muchas cosas de TypeScript como los Utility Types, keyof, etc. Y muchas otras formas de configurar el resolver.
Repo de mi proyecto


Nunca pares de aprender

Para los próximos cursos seria bueno que hiciera todo paso a paso se entiende más así, la mayoría de los videos de programación en platzi tienen ya archivos creados y no se si lo hacen para que el curso sea más corto, pero la verdad le baja calidad y no se aprende como es debido, por eso prefiero los cursos de udemy en cuanto a programación ya que puedes encontrarlos de ese tipo paso a paso

Para poder sacarle provecho a este curso hay que tener un conocimiento basico de typescript, apollo, prisma y graphql porque no te lleva paso a paso mientras crea el paso sino que te muestra codigo que ya existe

Les comparto el código del Mutation 15:40 -> Data completa del repo del profe

{
  "data": {
    "name": "Reed Avocado",
    "price": 1.18,
    "image": "/images/reed.jpg",
      "description":
        "Developed from a chance seedling found in 1948 by James S. Reed in California, this cultivar has large, round, green fruit with a smooth texture and dark, thick, glossy skin. Smooth and delicate, the flesh has a slightly nutty flavor. The skin ripens green. A Guatemalan type, it is hardy to −1 °C (30 °F). Tree size is about 5 by 4 m (16.4 by 13.1 ft)",
      "shape": "Round",
      "hardiness": "−1 °C",
      "taste": "Exquisite, is an avocado"
  }
}
Bueno, otro curso que no puedo aprender con éste profesor porque no explica su código solo pasa por encima y que adivinemos...

Muy bien explicado, me gusta está metodología porque no tengo que estar siguiendo el ritmo de profesor al escribir código ni estar pausando el vídeo. Así me queda claro todo y si tengo alguna duda o quiero experimentar algo, lo hago en el código ya hecho.

Mi repo. Le agregare un tag de un antes y después de esta clase a ver que tal queda luego 😄
https://github.com/MiguelHG2351/platzi-node-prisma-graphql

Me gusto que pusiera como ejercicio completar el esquema y los resolvers, pero me molesta que no se vaya con más calma explicando sus cambios, al final lo que va a servir para lo que sigue de su curso son sus cambios y solo saltarme al tag que está usando no me parece una buena manera de aprender.

Es solo una opinión, no se lo tomen personal.

Espero y esto se pudiera mejorar, ya que es el segundo curso que tomo de el y esperaría que pudiera mejorar por que llego a un punto en donde no puedo continuar si no me paso a la versión de sus tags.

Estructura del proyecto

🛠 Repositorio Link
.

.
En mi caso, sigo la estructura de mi proyecto, dandole al directorio GraphQL la siguiente estructura:

graphql
 └─⫸ enums
 └─⫸ models
	 └─⫸ Account
		 └─⫸ Account.entity.ts
		 └─⫸ Account.model.ts
		 └─⫸ Account.schema.ts
 └─⫸ scalars
 └─⫸ index.ts

Donde en cada elemento:

// Account.entity.ts
export interface Account {
    id: number
    email: string
    password: string
}

export type Query = Pick<Account, 'id'>
export type Payload = Pick<Account, 'email' | 'password'>
// Account.model.ts
import Model from '@models/Model'

import { Account, Query, Payload } from './Account.entity'

import accounts from '@db/mocks/account.mock'

export default class AccountModel extends Model<Account, Query, Payload> {
    /**
     * @description Find an account by id.
     * @param {Query} {id} Account ID.
     * @returns {Account | undefined} Account */
    findUnique({ id }: Query): Account | undefined {
        return accounts.find((account) => account.id === id)
    }
    /**
     * @description Find pool of accounts.
     * @returns {Account[]} Array of accounts. */
    findMany(): Account[] {
        return accounts
    }
    /**
     * @description Create an account.
     * @returns {Account} */
    create(payload: Payload): Account {
        return {
            id: 1,
            ...payload,
        }
    }
}

// Account.schema.ts
import { gql } from 'apollo-server'

import { Query, Payload } from './Account.entity'
import AccountModel from './Account.model'

import Error from '@controllers/Error.controller'

const accountModel = new AccountModel()

export default {
    Schema: gql`
        type Account {
            id: ID!
            email: String!
            password: String!
        }

        input CreateAccount {
            email: String!
            password: String!
        }

        extend type Query {
            account(id: ID!): Account!
            accounts: [Account!]!
        }
    `,
    Query: {
        account: (_: any, query: Query) => {
            const account = accountModel.findUnique(query)
            if (!account) throw new Error('NOT_FOUND')
            return account
        },
        accounts: () => {
            return accountModel.findMany()
        },
    },
    Mutation: {
        createAccount: (_: any, payload: Payload) => {
            return accountModel.create(payload)
        },
    },
}

Así quedó mi código del reto anterior:

import { ApolloServer } from 'apollo-server';


// Query
const typeDefs = `

    type Avo {
        _id: String
        name: String!
        price: Float!
        image: String
    }

    type Query {
        getAvos: [Avo]
    }

    input avoInput {
        _id: String
        name: String!
        price: Float!
        image: String
    }

    type Mutation {
        createAvo(input: avoInput): Avo
    }
`

let avos = [
    {
        "_id": "1",
        "name": "Avo 1",
        "price": 12.2,
        "image": "https://avo.com/",
    },
    {
        "_id": "2",
        "name": "Avo 2",
        "price": 123,
        "image": "https://avo.com/",
    },
    {
        "_id": "2",
        "name": "Avo 3",
        "price": 12311,
        "image": "https://avo.com/",
    },
];


// Resolvers
const resolvers = {
    Query: {
        getAvos: () => avos,
    },
    Mutation: {
        createAvo: (root: any, {input }: any) => {
            avos.push(input);
            return input;
        }
    }
}

// start server
const server = new ApolloServer({
    typeDefs,
    resolvers,
});

server.listen().then(({url}) => {console.log(`Listening on ${url}`)})

Schema Definition Language (SDL)

Especificación que define un schema y definirlo como una cadena.
.
Un schema define una colección de tipos y sus relaciones a través de types.
.
Cada relación define una unificación, lo que permite que los clientes puedan ver la información disponible, organizada.
.

💡 Un SDL no es responsable de la localidad real de la información y como es almacenada, es decir, se mantiene agnóstica.

.

Esquemas y tipos

Dado el siguiente código:

type Character {
  name: String!
  appearsIn: [Episode!]!
}

Character representa un Object Type representando un modelo. Dicho modelo pose fields como name y appearsIn.
.
Cada atributo cuenta con una tipo scalar , nulleable o requerido !.
.
Los tipos Query son estructuras que definen puntos de entradas para operaciones de lectura.

type Query {
  books: [Book]
  authors: [Author]
}

Los tipos Mutation son estructuras que definen puntos de entradas para operaciones de escritura.

type Mutation {
  addBook(title: String, author: String): Book
}

Los tipos Input son estructuras que definen una jerarquía de información para argumentos.
.

input BlogPostContent {
  title: String
  body: String
  media: [MediaDetails!]
}

input MediaDetails {
  format: MediaFormat!
  url: String!
}

enum MediaFormat {
  IMAGE
  VIDEO
}

Uniones e Interfaces

Las uniones son definiciones de tipos utilizados para campos o lista de campos.

union SearchResult = Book | Author

type Book {
  title: String!
}

type Author {
  name: String!
}

type Query {

  search(contains: String): [SearchResult!]
}

Una interfaz especifica un conjunto de campos que múltiples objetos pueden incluir.

interface Book {
  title: String!
  author: Author!
}

type Textbook implements Book {
  title: String! # Must be present
  author: Author! # Must be present
  courses: [Course!]!
}

type Query {
  books: [Book!] # Can include Textbook objects
}

Si un objeto implementa una interface, este debe incluir todos los campos de la interface.
.
Cuando se ocupa una interface como tipo de un capo, este puede incluir todos los objetos que implementan la interfaz.

Escalares

Por default, GraphQL incluye escalares por default tales como Int , Float, String, Boolean y ID.
.
Para definir un escalar, se necesita agregar al esquema la definición scalar Date.
.
Después se necesita determinar sus interacciones mediante una instancia de la clase GraphQLScalarType . De esta instancia, en particular, se necesita la representación del valor y serialized/deserialized.

import dayjs from 'dayjs'
import { GraphQLScalarType, Kind } from 'graphql'

export default new GraphQLScalarType({
    name: 'Date',
    description: 'Date custom scalar type',
    serialize: (date) => dayjs(date as string).toJSON(),
    parseValue: (date) => dayjs(date as number),
    parseLiteral: (ast) =>
        ast.kind === Kind.INT ? dayjs(parseInt(ast.value, 10)) : null,
})

.
Cada inicialización define los siguientes métodos:

  • Serialize - método que convierte una representación de valor a un formato compatible en JSON
    .
  • parseValue - método que convierte un valor en JSON a una representación de valor enviado como args
    .
  • parseLiteral - método que convierte un valor en Abstract Syntax Tree (AST) a una representación de valor.

Vengo del futuro, si no les funciona la query para obtener un avocado, pueden usar algo como esto:

type GetOneAvocadoArgs = {
  id: string
}

const getOneAvocado = (
  parent: unknown,
  { id }: GetOneAvocadoArgs,
  context: unknown
): Avocado | null => {
  const avocado = avocados.find(avo => avo.id === id)

  return avocado ?? null
}

Si su servidor no se reinicia automáticamente cuando se cambia el archivo .graphql, posiblemente es por la configuración de nodemon y se tenga que añadir un archivo /api/nodemon.json con la siguiente configuración:

{
  "watch": ["src"],
  "ext": "ts graphql",
  "exec": "ts-node --transpile-only src/index.ts"
}