Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
NotificationsYou must be signed in to change notification settings

curso-graphQL/3-academia-online

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

  1. Creación y configuración de ficheros necesarios
  2. Instalación de dependencias
  3. Ficheros JSON con la información de cursos
  4. Creación del servidor node express
  5. Schema
  6. Resolvers
  7. Configurar Apollo Server
  8. Obtener la lista de estudiantes
  9. Obtener un estudiante con el id indicado
  10. Obtener la lista de cursos
  11. Obtener un curso con el id indicado
  12. Lista de estudiantes de los cursos
  13. Mutations: Primeros pasos
  14. Definición del input CursoInput
  15. Añadir un nuevo curso
  16. Validaciones para no duplicar datos
  17. Modificar un curso
  18. Eliminar un curso

1. Creación y configuración de ficheros necesarios

Generamos elpackage.json mediante

npm init

Generamos eltsconfig.json mediante

npx tsc --init --rootDir src --outDir build --lib dom,es6 --module commonjs --target es6 --removeComments --resolveJsonModule true

2. Instalación de dependencias

Lista de dependencias que necesitaremos para trabajar en este proyecto:

Dependencias de producción:

npm install express graphql ncp http graphql-import-node compression cors lodash typescript graphql-tools graphql-playground-middleware-express apollo-server-express

Dependencias de desarrollo:

npm install @types/compression @types/express @types/cors @types/lodash @types/node @types/graphql -D

3. Ficheros JSON con la información de cursos

Creamos la carpetasrc y dentro de ella otra carpetadata donde pondremos los archivos JSON con los datos.

Creamos un archivodata.store.ts para importar los JSON.

importcursosfrom'./courses.json';importestudiantesfrom'./students.json';exportconstdatabase={  cursos,  estudiantes}

4. Creación del servidor node express

Configuramos los scripts delpackage.json

"scripts": {"start":"node build/server.js","build":"tsc -p . && ncp src/shchema build/schema","start:dev":"npm run build:dev","build:dev":"nodemon 'src/server.ts' --exec 'ts-node' src/server.ts -e ts,json,graphql"  },

Configuramos el servidor node express con los parámetros básicos

importcompressionfrom'compression';importcorsfrom'cors';import{createServer}from'http';constPORT=5200;constapp=express();app.use(cors());app.use(compression());app.get('/',(req,res)=>res.send('Hola a la academia online en GraphQL'));createServer(app).listen({port:PORT},()=>console.log(`Servidor Academia Online listo http://localhost:${PORT}`));

5. Schema

Creamos un directorioschema dentro desrc y en su interior el archivoschema.graphql en el que definiremos los tipos que vamos a necesitar en función de los datos que tenemos:

typeQuery {estudiantes:String}typeEstudiante {id:ID!name:String!email:String!website:Stringcourses: [Curso!]!}typeCurso {id:ID!title:String!description:Stringclases:Int!time:Floatlevel:Nivellogo:String!path:String!teacher:String!students: [Estudiante!]reviews: [Valoracion!]!}enumNivel{  TODOS  NOVATOS  INTERMEDIO  EXPERTO}typeValoracion {id:ID!name:String!points:Float!comment:String}

6. Resolvers

Creamos una carpetaresolvers ensrc con los siguientes archivos:

  • query.ts
import{IResolvers}from'graphql-tools';constquery:IResolvers={Query:{estudiantes():string{return"lista de estudiantes";//sólo para testear}}}exportdefaultquery;
  • resolversMap.ts
import{IResolvers}from'graphql-tools';importqueryfrom'./query';constresolversMap:IResolvers={  ...query}exportdefaultresolversMap;

En la carpetasrc/schema creamos un archivoindex.ts que contendrá lo siguiente:

import{GraphQLSchema}from'graphql';import'graphql-import-node';import{makeExecutableSchema}from'graphql-tools';importtypeDefsfrom'./schema.graphql';importresolversfrom'../resolvers/resolversMap';constschema:GraphQLSchema=makeExecutableSchema({  typeDefs,  resolvers})exportdefaultschema;

7. Configurar Apollo Server

Modificamosserver.ts

...import{ApolloServer}from'apollo-server-express';importschemafrom'./schema/index';importexpressPlayGroundfrom'graphql-playground-middleware-express';......constserver=newApolloServer({  schema,introspection:true});server.applyMiddleware({app});app.get('/',expressPlayGround({endpoint:'/graphql'}));createServer(app).listen({port:PORT},()=>console.log(`Servidor Academia Online listo http://localhost:${PORT}`));...

8. Resolvers - Queries - Lista de estudiantes

Modificamos enschema.graphql la query:

typeQuery {"Lista de los estudiantes de la academia"estudiantes: [Estudiante!]!}

Igualmente modificamos enresolvers/query.ts la constantequery:

constquery:IResolvers={Query:{estudiantes():any{returndatabase.estudiantes;}}}

Una vez hecho esto, ya podemos lanzar en apollo server la query a estudiantes estableciendo los parámetros que queremos que nos devuelva.

Imagen1

Para el caso de querer recuperar la información de los cursos de cada estudiante necesitaremos otro resolver.

Creamos en la carpetaresolvers un nuevo archivotypes.ts:

import{IResolvers}from'graphql-tools';import{database}from'../data/data.store';import_from'lodash';consttype:IResolvers={Estudiante:{courses:parent=>{constcursosLista:any[]=[]parent.courses.map((curso:string)=>{cursosLista.push(_.find(database.cursos,['id',curso]))})returncursosLista}}}exportdefaulttype;

Debemos añadir el nuevo resolver aresolvers/resolverMap.ts

...importtypefrom'./type';constresolversMap:IResolvers={    ...query,    ...type}...

9. Resolvers - Queries - Un estudiante

Primero modificamosschema.graphql para añadir la query de un solo estudiante:

typeQuery {"Lista de los estudiantes de la academia"estudiantes: [Estudiante!]!,"Información del estudiante de la academia seleccionado por ID"estudiante(id:ID!):Estudiante!!,}

Luego añadimos el nuevo resolver para obtener un solo estudiante aresolvers/query.ts:

constquery:IResolvers={Query:{estudiantes():any{returndatabase.estudiantes;},estudiante(__:void,{ id}):any{returndatabase.estudiantes.find(estudiante=>estudiante.id===id);}}}

Con esto ya tenemos disponible la info en la api.

Imagen2

En caso de que el elemento que buscamos no se encuentre, podemos devolver una respuesta que mantenga el formato que se espera, pero que indique de forma clara que no se han encontrado registros. Para conseguirlo, modificamos el resolver:

...estudiante(__:void,{ id}):any{constfound=database.estudiantes.find(estudiante=>estudiante.id===id);returnfound||{id:-1,name:`No se ha encontrado el estudiante con ID${id}`,email:'',courses:[]}}...

Imagen3

10. Obtener la lista de cursos

Prodedemos de igual forma que hicimos para la lista de estudiantes: Primero modificamos la query en el schema.

typeQuery {"Lista de los estudiantes de la academia"estudiantes: [Estudiante!]!,"Información del estudiante de la academia seleccionado por ID"estudiante(id:ID!):Estudiante!,"Lista de los cursos de la academia"cursos: [Curso!]!}

Luego modificamos el resolver enquery.ts:

constquery:IResolvers={Query:{  ...cursos():any{      returndatabase.cursos;},  ...

11. Obtener un curso con el id indicado

Procedemos de la misma forma, modificando primero el schema:

typeQuery {  ..."Información del curso de la academia seleccionado por ID"curso(id:ID!):Curso!,}

Luego modificamos el resolver:

constquery:IResolvers={Query:{    ...curso(__:void,{ id}):any{const found=database.cursos.find(curso=>curso.id===id);returnfound||{id:-1,title:`No se ha encontrado el curso con ID${id}`,clases:-1,logo:'',path:'',teacher:'',reviews:[]}},}}

12. Lista de estudiantes de los cursos

Vamos también a añadir un nuevo resolver para poder obtener los estudiantes que están inscritos a un curso. Para ello modificamosresolvers/type.ts:

consttype:IResolvers={  ...Curso:{students:parent=>{constestudiantesLista:any[]=[]database.estudiantes.map((estudiante:any)=>{if(!!estudiante.courses.find((course:string)=>course===parent.id)){estudiantesLista.push(estudiante)}});returnestudiantesLista},path:parent=>`http://www.udemy.com${parent.path}`}

Como en este caso, los estudiantes de un curso no es un parámetro obligatorio, contemplamos el caso en el que parent.students sea undefined.

Adicionalmente hemos modificado cómo se entrega la información del path del curso para incluir la url completa:


13. Mutations: primeros pasos

Una vez hemos terminado de configurar lasqueries para obtener datos, vamos a empezar a configurar losmutations para poder añadir nuevos datos.

Enschema-graphql añadimos un nuevo tipo:

typeMutation {"Añadir nuevo curso del al academia"cursoNuevo(curso:CursoInput!):Curso!"Modificar curso del al academia existente"modificarCurso(curso:CursoInput!):Curso!"Eliminar curso del al academia seleccionado por su ID"eliminarCurso(id:ID!):Curso!}

En el directorioresolvers creamos un nuevo ficheromutation.ts donde definiremos las distintas acciones más adelante.

import{IResolvers}from'graphql-tools';import_from'lodash';constmutation:IResolvers={}exportdefaultmutation;

Debemos añadir este archivo alresolversMap.ts

constresolversMap:IResolvers={  ...query,  ...type,  ...mutation,}

15. Definición del input CursoInput

En el punto anterior indicamos que el parámetor curso para añadir/modificar un curso era del tipo CursoInput.

Definimos este tipo enschema.graphql tomando como referencia las propiedades del typeCurso:

inputCursoInput {id:IDtitle:String!description:Stringclases:Int!time:Floatlevel:Nivellogo:String!path:String!teacher:String!}

En este caso ID no puede ser required porque al crear el curso no tenemos su valor y va como null. Del mismo modo, no incluimos los atributos reviews ni students porque al crear un nuevo curso estas propiedades no existen.


15. Añadir un nuevo curso

En el archivomutation.ts añadimos el mutation para añadir un nuevo curso:

Mutation: {cursoNuevo(__: void, { curso }):any {constnuevoCurso = {id:String(database.cursos.length + 1),title:curso.title,description:curso.description,clases:curso.clases,time:curso.time,level:curso.level,logo:curso.logo,path:curso.path,teacher:curso.teacher,reviews: [],students: []      };database.cursos.push(nuevoCurso);returnnuevoCurso;    }  }

Una vez hecho esto, ya podemos añadir un nuevo curso a través de apollo server:

Imagen4


16. Validaciones para no duplicar datos

Para realizar esta validación, en el mutation ponemos una condición que compruebe que el nuevo curso no existe antes de formar el objeto nuevoCurso:

if(database.cursos.find(item=>curso.title===item.title)){return{id:-1,title:'El curso ya existe con este título',clases:0,logo:'',path:'',teacher:'',reviews:[],}}

17. Modificar un curso

Creamos el nuevo mutation:

modificarCurso(__:void,{ curso}):any{constfoundIndex=_.findIndex(database.cursos,item=>curso.id===item.id)if(foundIndex>0){database.cursos[foundIndex]={ ...database.cursos[0], ...curso};returndatabase.cursos[foundIndex];}return{id:-1,title:'No existe curso con este id',clases:0,logo:'',path:'',teacher:'',reviews:[],}}

18. Eliminar un curso

Creamos el nuevo mutation:

eliminarCurso(__:void,{ id}):any{constfound=_.remove(database.cursos,item=>id===item.id)returnfound[0]||{id:-1,title:'No existe curso con este id',clases:0,logo:'',path:'',teacher:'',reviews:[],}}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp