From d87ba843ab090a64a9a758c9e3d2cf3f15ec52fe Mon Sep 17 00:00:00 2001 From: David Anyatonwu Date: Wed, 21 Aug 2024 12:26:57 +0000 Subject: [PATCH 1/2] Add JSONPlaceholder example configurations --- examples/jsonplaceholder.graphql | 265 ++++++++++++- examples/jsonplaceholder.json | 620 +++++++++++++++++++++++++++--- examples/jsonplaceholder.yml | 632 ++++++++++++++++++++++++++++++- 3 files changed, 1445 insertions(+), 72 deletions(-) diff --git a/examples/jsonplaceholder.graphql b/examples/jsonplaceholder.graphql index b514aad597..b8c791e2f1 100644 --- a/examples/jsonplaceholder.graphql +++ b/examples/jsonplaceholder.graphql @@ -1,28 +1,281 @@ +# Define the schema with upstream configuration and server settings schema + # Specify server configuration: Start GraphQL server at 0.0.0.0:8000 @server(port: 8000) - @upstream(baseURL: "http://jsonplaceholder.typicode.com", httpCache: 42, batch: {delay: 100}) { + # Specify a base URL for all HTTP requests + @upstream(baseURL: "https://jsonplaceholder.typicode.com") { query: Query + mutation: Mutation } +# Define the Query type with various fields type Query { - posts: [Post] @http(path: "/posts") - users: [User] @http(path: "/users") + # Fetch a post by ID + post(id: Int!): Post @http(path: "/posts/{{.args.id}}") + # Fetch all posts by a specific user + posts(user: Id): [Post] @http(path: "/posts?userId={{.args.user}}") + # Fetch a comment by ID + comment(id: Int!): Comment @http(path: "/comments/{{.args.id}}") + # Fetch all comments on a specific post + comments(post: Id): [Comment] @http(path: "/comments?postId={{.args.post}}") + # Fetch an album by ID + album(id: Int!): Album @http(path: "/albums/{{.args.id}}") + # Fetch all albums by a specific user + albums(user: Id): [Album] @http(path: "/albums?userId={{.args.user}}") + # Fetch a photo by ID + photo(id: Int!): Photo @http(path: "/photos/{{.args.id}}") + # Fetch all photos in a specific album + photos(album: Id): [Photo] @http(path: "/photos?albumId={{.args.album}}") + # Fetch a todo by ID + todo(id: Int!): Todo @http(path: "/todos/{{.args.id}}") + # Fetch all todos by a specific user + todos(user: Id): [Todo] @http(path: "/todos?userId={{.args.user}}") + # Fetch a user by ID user(id: Int!): User @http(path: "/users/{{.args.id}}") + # Fetch all users + users: [User] @http(path: "/users") +} + +# Define the Mutation type with various fields for creating, updating, and deleting resources +type Mutation { + # Create a new post + createPost(input: PostInput!): Post @http(method: "POST", path: "/posts", body: "{{.args.input}}") + # Update an existing post + updatePost(id: Int!, input: PostInput!): Post + @http(method: "PUT", path: "/posts/{{.args.id}}", body: "{{.args.input}}") + # Patch (partially update) an existing post + patchPost(id: Int!, input: PartialPostInput!): Post + @http(method: "PATCH", path: "/posts/{{.args.id}}", body: "{{.args.input}}") + # Delete a post + deletePost(id: Int!): Boolean @http(method: "DELETE", path: "/posts/{{.args.id}}") + + # Create a new comment + createComment(input: CommentInput!): Comment @http(method: "POST", path: "/comments", body: "{{.args.input}}") + # Update an existing comment + updateComment(id: Int!, input: CommentInput!): Comment + @http(method: "PUT", path: "/comments/{{.args.id}}", body: "{{.args.input}}") + # Delete a comment + deleteComment(id: Int!): Boolean @http(method: "DELETE", path: "/comments/{{.args.id}}") + + # Create a new album + createAlbum(input: AlbumInput!): Album @http(method: "POST", path: "/albums", body: "{{.args.input}}") + # Update an existing album + updateAlbum(id: Int!, input: AlbumInput!): Album + @http(method: "PUT", path: "/albums/{{.args.id}}", body: "{{.args.input}}") + # Delete an album + deleteAlbum(id: Int!): Boolean @http(method: "DELETE", path: "/albums/{{.args.id}}") + + # Create a new photo + createPhoto(input: PhotoInput!): Photo @http(method: "POST", path: "/photos", body: "{{.args.input}}") + # Update an existing photo + updatePhoto(id: Int!, input: PhotoInput!): Photo + @http(method: "PUT", path: "/photos/{{.args.id}}", body: "{{.args.input}}") + # Delete a photo + deletePhoto(id: Int!): Boolean @http(method: "DELETE", path: "/photos/{{.args.id}}") + + # Create a new todo + createTodo(input: TodoInput!): Todo @http(method: "POST", path: "/todos", body: "{{.args.input}}") + # Update an existing todo + updateTodo(id: Int!, input: TodoInput!): Todo + @http(method: "PUT", path: "/todos/{{.args.id}}", body: "{{.args.input}}") + # Delete a todo + deleteTodo(id: Int!): Boolean @http(method: "DELETE", path: "/todos/{{.args.id}}") + + # Create a new user + createUser(input: UserInput!): User @http(method: "POST", path: "/users", body: "{{.args.input}}") + # Update an existing user + updateUser(id: Int!, input: UserInput!): User + @http(method: "PUT", path: "/users/{{.args.id}}", body: "{{.args.input}}") + # Delete a user + deleteUser(id: Int!): Boolean @http(method: "DELETE", path: "/users/{{.args.id}}") +} + +# Define the Post type with its fields and related queries +type Post { + id: Int! + userId: Int! + title: String! + body: String! + # Fetch the user who created the post + user: User @call(steps: [{query: "user", args: {id: "{{.value.userId}}"}}]) + # Fetch all comments on the post + comments: [Comment] @call(steps: [{query: "comments", args: {post: "{{.value.id}}"}}]) +} + +# Define the Comment type with its fields and related queries +type Comment { + id: Int! + postId: Int! + name: String! + email: String! + body: String! + # Fetch the post to which the comment belongs + post: Post @call(steps: [{query: "post", args: {id: "{{.value.postId}}"}}]) } +# Define the Album type with its fields and related queries +type Album { + id: Int! + userId: Int! + title: String! + # Fetch the user who created the album + user: User @call(steps: [{query: "user", args: {id: "{{.value.userId}}"}}]) + # Fetch all photos in the album + photos: [Photo] @call(steps: [{query: "photos", args: {album: "{{.value.id}}"}}]) +} + +# Define the Photo type with its fields and related queries +type Photo { + id: Int! + albumId: Int! + title: String! + url: String! + thumbnailUrl: String! + # Fetch the album to which the photo belongs + album: Album @call(steps: [{query: "album", args: {id: "{{.value.albumId}}"}}]) +} + +# Define the Todo type with its fields and related queries +type Todo { + id: Int! + userId: Int! + title: String! + completed: Boolean! + # Fetch the user who created the todo + user: User @call(steps: [{query: "user", args: {id: "{{.value.userId}}"}}]) +} + +# Define the User type with its fields and related queries type User { id: Int! name: String! username: String! email: String! + address: Address phone: String website: String + company: Company + # Fetch all posts by the user + posts: [Post] @call(steps: [{query: "posts", args: {user: "{{.value.id}}"}}]) + # Fetch all albums by the user + albums: [Album] @call(steps: [{query: "albums", args: {user: "{{.value.id}}"}}]) + # Fetch all todos by the user + todos: [Todo] @call(steps: [{query: "todos", args: {user: "{{.value.id}}"}}]) } -type Post { - id: Int! +# Define the Address type with its fields +type Address { + street: String + suite: String + city: String + zipcode: String + geo: Geo +} + +# Define the Geo type with its fields +type Geo { + lat: String + lng: String +} + +# Define the Company type with its fields +type Company { + name: String + catchPhrase: String + bs: String +} + +# Define the input type for creating a post +input PostInput { userId: Int! title: String! body: String! - user: User @call(steps: [{query: "user", args: {id: "{{.value.userId}}"}}]) +} + +# Define the input type for partially updating a post +input PartialPostInput { + userId: Int + title: String + body: String +} + +# Define the input type for creating a comment +input CommentInput { + postId: Int! + name: String! + email: String! + body: String! +} + +# Define the input type for creating an album +input AlbumInput { + userId: Int! + title: String! +} + +# Define the input type for creating a photo +input PhotoInput { + albumId: Int! + title: String! + url: String! + thumbnailUrl: String! +} + +# Define the input type for creating a todo +input TodoInput { + userId: Int! + title: String! + completed: Boolean! +} + +# Define the input type for creating a user +input UserInput { + name: String! + username: String! + email: String! + address: AddressInput + phone: String + website: String + company: CompanyInput +} + +# Define the input type for the address field +input AddressInput { + street: String + suite: String + city: String + zipcode: String + geo: GeoInput +} + +# Define the input type for the geo field +input GeoInput { + lat: String + lng: String +} + +# Define the input type for the company field +input CompanyInput { + name: String + catchPhrase: String + bs: String +} + +# Define a complex query type for fetching user data along with posts and comments +type ComplexQuery { + userWithPostsAndComments(userId: Int!): UserWithPostsAndComments + @call( + steps: [ + {query: "user", args: {id: "{{.args.userId}}"}} + {query: "posts", args: {user: "{{.value.id}}"}} + {query: "comments", args: {post: "{{.value.posts.0.id}}"}} + ] + ) +} + +# Define the UserWithPostsAndComments type with fields for user, posts, and comments +type UserWithPostsAndComments { + user: User + posts: [Post] + comments: [Comment] } diff --git a/examples/jsonplaceholder.json b/examples/jsonplaceholder.json index cce3f0d6b4..bce0435f18 100644 --- a/examples/jsonplaceholder.json +++ b/examples/jsonplaceholder.json @@ -1,91 +1,617 @@ { - "$schema": "../generated/.tailcallrc.schema.json", "server": { - "hostname": "0.0.0.0", - "port": 8000 + "port": 8000, + "queryValidation": false, + "hostname": "0.0.0.0" }, "upstream": { - "baseURL": "http://jsonplaceholder.typicode.com", + "baseURL": "https://jsonplaceholder.typicode.com", "httpCache": 42 }, "schema": { - "query": "Query" + "query": "Query", + "mutation": "Mutation" }, "types": { - "Post": { + "Query": { "fields": { - "body": { - "type": "String", - "required": true + "post": { + "type": "Post", + "args": { + "id": {"type": "Int", "required": true} + }, + "http": { + "path": "/posts/{{.args.id}}" + } + }, + "posts": { + "type": "Post", + "list": true, + "args": { + "user": {"type": "Id", "required": true} + }, + "http": { + "path": "/posts?userId={{.args.user}}" + } + }, + "comment": { + "type": "Comment", + "args": { + "id": {"type": "Int", "required": true} + }, + "http": { + "path": "/comments/{{.args.id}}" + } + }, + "comments": { + "type": "Comment", + "list": true, + "args": { + "post": {"type": "Id", "required": true} + }, + "http": { + "path": "/comments?postId={{.args.post}}" + } + }, + "album": { + "type": "Album", + "args": { + "id": {"type": "Int", "required": true} + }, + "http": { + "path": "/albums/{{.args.id}}" + } + }, + "albums": { + "type": "Album", + "list": true, + "args": { + "user": {"type": "Id", "required": true} + }, + "http": { + "path": "/albums?userId={{.args.user}}" + } + }, + "photo": { + "type": "Photo", + "args": { + "id": {"type": "Int", "required": true} + }, + "http": { + "path": "/photos/{{.args.id}}" + } + }, + "photos": { + "type": "Photo", + "list": true, + "args": { + "album": {"type": "Id", "required": true} + }, + "http": { + "path": "/photos?albumId={{.args.album}}" + } }, - "id": { - "type": "Int", - "required": true + "todo": { + "type": "Todo", + "args": { + "id": {"type": "Int", "required": true} + }, + "http": { + "path": "/todos/{{.args.id}}" + } }, - "title": { - "type": "String", - "required": true + "todos": { + "type": "Todo", + "list": true, + "args": { + "user": {"type": "Id", "required": true} + }, + "http": { + "path": "/todos?userId={{.args.user}}" + } }, "user": { "type": "User", + "args": { + "id": {"type": "Int", "required": true} + }, "http": { - "path": "/users/{{value.userId}}" + "path": "/users/{{.args.id}}" } }, - "userId": { - "type": "Int", - "required": true + "users": { + "type": "User", + "list": true, + "http": { + "path": "/users" + } } } }, - "Query": { + "Mutation": { "fields": { - "posts": { + "createPost": { "type": "Post", - "list": true, + "args": { + "input": {"type": "PostInput", "required": true} + }, "http": { - "path": "/posts" + "method": "POST", + "path": "/posts", + "body": "{{.args.input}}" } }, - "user": { + "updatePost": { + "type": "Post", + "args": { + "id": {"type": "Int", "required": true}, + "input": {"type": "PostInput", "required": true} + }, + "http": { + "method": "PUT", + "path": "/posts/{{.args.id}}", + "body": "{{.args.input}}" + } + }, + "patchPost": { + "type": "Post", + "args": { + "id": {"type": "Int", "required": true}, + "input": {"type": "PartialPostInput", "required": true} + }, + "http": { + "method": "PATCH", + "path": "/posts/{{.args.id}}", + "body": "{{.args.input}}" + } + }, + "deletePost": { + "type": "Boolean", + "args": { + "id": {"type": "Int", "required": true} + }, + "http": { + "method": "DELETE", + "path": "/posts/{{.args.id}}" + } + }, + "createComment": { + "type": "Comment", + "args": { + "input": {"type": "CommentInput", "required": true} + }, + "http": { + "method": "POST", + "path": "/comments", + "body": "{{.args.input}}" + } + }, + "updateComment": { + "type": "Comment", + "args": { + "id": {"type": "Int", "required": true}, + "input": {"type": "CommentInput", "required": true} + }, + "http": { + "method": "PUT", + "path": "/comments/{{.args.id}}", + "body": "{{.args.input}}" + } + }, + "deleteComment": { + "type": "Boolean", + "args": { + "id": {"type": "Int", "required": true} + }, + "http": { + "method": "DELETE", + "path": "/comments/{{.args.id}}" + } + }, + "createAlbum": { + "type": "Album", + "args": { + "input": {"type": "AlbumInput", "required": true} + }, + "http": { + "method": "POST", + "path": "/albums", + "body": "{{.args.input}}" + } + }, + "updateAlbum": { + "type": "Album", + "args": { + "id": {"type": "Int", "required": true}, + "input": {"type": "AlbumInput", "required": true} + }, + "http": { + "method": "PUT", + "path": "/albums/{{.args.id}}", + "body": "{{.args.input}}" + } + }, + "deleteAlbum": { + "type": "Boolean", + "args": { + "id": {"type": "Int", "required": true} + }, + "http": { + "method": "DELETE", + "path": "/albums/{{.args.id}}" + } + }, + "createPhoto": { + "type": "Photo", + "args": { + "input": {"type": "PhotoInput", "required": true} + }, + "http": { + "method": "POST", + "path": "/photos", + "body": "{{.args.input}}" + } + }, + "updatePhoto": { + "type": "Photo", + "args": { + "id": {"type": "Int", "required": true}, + "input": {"type": "PhotoInput", "required": true} + }, + "http": { + "method": "PUT", + "path": "/photos/{{.args.id}}", + "body": "{{.args.input}}" + } + }, + "deletePhoto": { + "type": "Boolean", + "args": { + "id": {"type": "Int", "required": true} + }, + "http": { + "method": "DELETE", + "path": "/photos/{{.args.id}}" + } + }, + "createTodo": { + "type": "Todo", + "args": { + "input": {"type": "TodoInput", "required": true} + }, + "http": { + "method": "POST", + "path": "/todos", + "body": "{{.args.input}}" + } + }, + "updateTodo": { + "type": "Todo", + "args": { + "id": {"type": "Int", "required": true}, + "input": {"type": "TodoInput", "required": true} + }, + "http": { + "method": "PUT", + "path": "/todos/{{.args.id}}", + "body": "{{.args.input}}" + } + }, + "deleteTodo": { + "type": "Boolean", + "args": { + "id": {"type": "Int", "required": true} + }, + "http": { + "method": "DELETE", + "path": "/todos/{{.args.id}}" + } + }, + "createUser": { + "type": "User", + "args": { + "input": {"type": "UserInput", "required": true} + }, + "http": { + "method": "POST", + "path": "/users", + "body": "{{.args.input}}" + } + }, + "updateUser": { "type": "User", "args": { - "id": { - "type": "Int", - "required": true - } + "id": {"type": "Int", "required": true}, + "input": {"type": "UserInput", "required": true} + }, + "http": { + "method": "PUT", + "path": "/users/{{.args.id}}", + "body": "{{.args.input}}" + } + }, + "deleteUser": { + "type": "Boolean", + "args": { + "id": {"type": "Int", "required": true} }, "http": { - "path": "/users/{{args.id}}" + "method": "DELETE", + "path": "/users/{{.args.id}}" } } } }, - "User": { + "Post": { "fields": { - "email": { - "type": "String", - "required": true - }, - "id": { - "type": "Int", - "required": true + "id": {"type": "Int", "required": true}, + "userId": {"type": "Int", "required": true}, + "title": {"type": "String", "required": true}, + "body": {"type": "String", "required": true}, + "user": { + "type": "User", + "call": { + "steps": [{"query": "user", "args": {"id": "{{.value.userId}}"}}] + } }, - "name": { - "type": "String", - "required": true + "comments": { + "type": "Comment", + "list": true, + "call": { + "steps": [ + { + "query": "comments", + "args": {"post": "{{.value.id}}"} + } + ] + } + } + } + }, + "Comment": { + "fields": { + "id": {"type": "Int", "required": true}, + "postId": {"type": "Int", "required": true}, + "name": {"type": "String", "required": true}, + "email": {"type": "String", "required": true}, + "body": {"type": "String", "required": true}, + "post": { + "type": "Post", + "call": { + "steps": [{"query": "post", "args": {"id": "{{.value.postId}}"}}] + } + } + } + }, + "Album": { + "fields": { + "id": {"type": "Int", "required": true}, + "userId": {"type": "Int", "required": true}, + "title": {"type": "String", "required": true}, + "user": { + "type": "User", + "call": { + "steps": [{"query": "user", "args": {"id": "{{.value.userId}}"}}] + } }, - "phone": { - "type": "String" + "photos": { + "type": "Photo", + "list": true, + "call": { + "steps": [ + { + "query": "photos", + "args": {"album": "{{.value.id}}"} + } + ] + } + } + } + }, + "Photo": { + "fields": { + "id": {"type": "Int", "required": true}, + "albumId": {"type": "Int", "required": true}, + "title": {"type": "String", "required": true}, + "url": {"type": "String", "required": true}, + "thumbnailUrl": {"type": "String", "required": true}, + "album": { + "type": "Album", + "call": { + "steps": [{"query": "album", "args": {"id": "{{.value.albumId}}"}}] + } + } + } + }, + "Todo": { + "fields": { + "id": {"type": "Int", "required": true}, + "userId": {"type": "Int", "required": true}, + "title": {"type": "String", "required": true}, + "completed": {"type": "Boolean", "required": true}, + "user": { + "type": "User", + "call": { + "steps": [{"query": "user", "args": {"id": "{{.value.userId}}"}}] + } + } + } + }, + "User": { + "fields": { + "id": {"type": "Int", "required": true}, + "name": {"type": "String", "required": true}, + "username": {"type": "String", "required": true}, + "email": {"type": "String", "required": true}, + "address": {"type": "Address"}, + "phone": {"type": "String"}, + "website": {"type": "String"}, + "company": {"type": "Company"}, + "posts": { + "type": "Post", + "list": true, + "call": { + "steps": [ + { + "query": "posts", + "args": {"user": "{{.value.id}}"} + } + ] + } }, - "username": { - "type": "String", - "required": true + "albums": { + "type": "Album", + "list": true, + "call": { + "steps": [ + { + "query": "albums", + "args": {"user": "{{.value.id}}"} + } + ] + } }, - "website": { - "type": "String" + "todos": { + "type": "Todo", + "list": true, + "call": { + "steps": [ + { + "query": "todos", + "args": {"user": "{{.value.id}}"} + } + ] + } } } + }, + "Address": { + "fields": { + "street": {"type": "String"}, + "suite": {"type": "String"}, + "city": {"type": "String"}, + "zipcode": {"type": "String"}, + "geo": {"type": "Geo"} + } + }, + "Geo": { + "fields": { + "lat": {"type": "String"}, + "lng": {"type": "String"} + } + }, + "Company": { + "fields": { + "name": {"type": "String"}, + "catchPhrase": {"type": "String"}, + "bs": {"type": "String"} + } + }, + "PostInput": { + "fields": { + "userId": {"type": "Int", "required": true}, + "title": {"type": "String", "required": true}, + "body": {"type": "String", "required": true} + } + }, + "PartialPostInput": { + "fields": { + "userId": {"type": "Int"}, + "title": {"type": "String"}, + "body": {"type": "String"} + } + }, + "CommentInput": { + "fields": { + "postId": {"type": "Int", "required": true}, + "name": {"type": "String", "required": true}, + "email": {"type": "String", "required": true}, + "body": {"type": "String", "required": true} + } + }, + "AlbumInput": { + "fields": { + "userId": {"type": "Int", "required": true}, + "title": {"type": "String", "required": true} + } + }, + "PhotoInput": { + "fields": { + "albumId": {"type": "Int", "required": true}, + "title": {"type": "String", "required": true}, + "url": {"type": "String", "required": true}, + "thumbnailUrl": {"type": "String", "required": true} + } + }, + "TodoInput": { + "fields": { + "userId": {"type": "Int", "required": true}, + "title": {"type": "String", "required": true}, + "completed": {"type": "Boolean", "required": true} + } + }, + "UserInput": { + "fields": { + "name": {"type": "String", "required": true}, + "username": {"type": "String", "required": true}, + "email": {"type": "String", "required": true}, + "address": {"type": "AddressInput"}, + "phone": {"type": "String"}, + "website": {"type": "String"}, + "company": {"type": "CompanyInput"} + } + }, + "AddressInput": { + "fields": { + "street": {"type": "String"}, + "suite": {"type": "String"}, + "city": {"type": "String"}, + "zipcode": {"type": "String"}, + "geo": {"type": "GeoInput"} + } + }, + "GeoInput": { + "fields": { + "lat": {"type": "String"}, + "lng": {"type": "String"} + } + }, + "CompanyInput": { + "fields": { + "name": {"type": "String"}, + "catchPhrase": {"type": "String"}, + "bs": {"type": "String"} + } + }, + "ComplexQuery": { + "fields": { + "userWithPostsAndComments": { + "type": "UserWithPostsAndComments", + "args": { + "userId": {"type": "Int", "required": true} + }, + "call": { + "steps": [ + {"query": "user", "args": {"id": "{{.args.userId}}"}}, + { + "query": "posts", + "args": {"user": "{{.value.id}}"} + }, + { + "query": "comments", + "args": {"post": "{{.value.posts.0.id}}"} + } + ] + } + } + } + }, + "UserWithPostsAndComments": { + "fields": { + "user": {"type": "User"}, + "posts": {"type": "Post", "list": true}, + "comments": {"type": "Comment", "list": true} + } } } } diff --git a/examples/jsonplaceholder.yml b/examples/jsonplaceholder.yml index 57f712130f..a75ccf4044 100644 --- a/examples/jsonplaceholder.yml +++ b/examples/jsonplaceholder.yml @@ -1,60 +1,654 @@ server: - hostname: 0.0.0.0 port: 8000 + queryValidation: false + hostname: "0.0.0.0" upstream: - baseURL: http://jsonplaceholder.typicode.com + baseURL: https://jsonplaceholder.typicode.com httpCache: 42 schema: query: Query + mutation: Mutation types: + Query: + fields: + post: + type: Post + args: + id: + type: Int + required: true + http: + path: /posts/{{.args.id}} + posts: + type: Post + list: true + args: + user: + type: Id + required: true + http: + path: /posts?userId={{.args.user}} + comment: + type: Comment + args: + id: + type: Int + required: true + http: + path: /comments/{{.args.id}} + comments: + type: Comment + list: true + args: + post: + type: Id + required: true + http: + path: /comments?postId={{.args.post}} + album: + type: Album + args: + id: + type: Int + required: true + http: + path: /albums/{{.args.id}} + albums: + type: Album + list: true + args: + user: + type: Id + required: true + http: + path: /albums?userId={{.args.user}} + photo: + type: Photo + args: + id: + type: Int + required: true + http: + path: /photos/{{.args.id}} + photos: + type: Photo + list: true + args: + album: + type: Id + required: true + http: + path: /photos?albumId={{.args.album}} + todo: + type: Todo + args: + id: + type: Int + required: true + http: + path: /todos/{{.args.id}} + todos: + type: Todo + list: true + args: + user: + type: Id + required: true + http: + path: /todos?userId={{.args.user}} + user: + type: User + args: + id: + type: Int + required: true + http: + path: /users/{{.args.id}} + users: + type: User + list: true + http: + path: /users + Mutation: + fields: + createPost: + type: Post + args: + input: + type: PostInput + required: true + http: + method: POST + path: /posts + body: "{{.args.input}}" + updatePost: + type: Post + args: + id: + type: Int + required: true + input: + type: PostInput + required: true + http: + method: PUT + path: /posts/{{.args.id}} + body: "{{.args.input}}" + patchPost: + type: Post + args: + id: + type: Int + required: true + input: + type: PartialPostInput + required: true + http: + method: PATCH + path: /posts/{{.args.id}} + body: "{{.args.input}}" + deletePost: + type: Boolean + args: + id: + type: Int + required: true + http: + method: DELETE + path: /posts/{{.args.id}} + createComment: + type: Comment + args: + input: + type: CommentInput + required: true + http: + method: POST + path: /comments + body: "{{.args.input}}" + updateComment: + type: Comment + args: + id: + type: Int + required: true + input: + type: CommentInput + required: true + http: + method: PUT + path: /comments/{{.args.id}} + body: "{{.args.input}}" + deleteComment: + type: Boolean + args: + id: + type: Int + required: true + http: + method: DELETE + path: /comments/{{.args.id}} + createAlbum: + type: Album + args: + input: + type: AlbumInput + required: true + http: + method: POST + path: /albums + body: "{{.args.input}}" + updateAlbum: + type: Album + args: + id: + type: Int + required: true + input: + type: AlbumInput + required: true + http: + method: PUT + path: /albums/{{.args.id}} + body: "{{.args.input}}" + deleteAlbum: + type: Boolean + args: + id: + type: Int + required: true + http: + method: DELETE + path: /albums/{{.args.id}} + createPhoto: + type: Photo + args: + input: + type: PhotoInput + required: true + http: + method: POST + path: /photos + body: "{{.args.input}}" + updatePhoto: + type: Photo + args: + id: + type: Int + required: true + input: + type: PhotoInput + required: true + http: + method: PUT + path: /photos/{{.args.id}} + body: "{{.args.input}}" + deletePhoto: + type: Boolean + args: + id: + type: Int + required: true + http: + method: DELETE + path: /photos/{{.args.id}} + createTodo: + type: Todo + args: + input: + type: TodoInput + required: true + http: + method: POST + path: /todos + body: "{{.args.input}}" + updateTodo: + type: Todo + args: + id: + type: Int + required: true + input: + type: TodoInput + required: true + http: + method: PUT + path: /todos/{{.args.id}} + body: "{{.args.input}}" + deleteTodo: + type: Boolean + args: + id: + type: Int + required: true + http: + method: DELETE + path: /todos/{{.args.id}} + createUser: + type: User + args: + input: + type: UserInput + required: true + http: + method: POST + path: /users + body: "{{.args.input}}" + updateUser: + type: User + args: + id: + type: Int + required: true + input: + type: UserInput + required: true + http: + method: PUT + path: /users/{{.args.id}} + body: "{{.args.input}}" + deleteUser: + type: Boolean + args: + id: + type: Int + required: true + http: + method: DELETE + path: /users/{{.args.id}} Post: fields: + id: + type: Int + required: true + userId: + type: Int + required: true + title: + type: String + required: true + body: + type: String + required: true + user: + type: User + call: + steps: + - query: user + args: + id: "{{.value.userId}}" + comments: + type: Comment + list: true + call: + steps: + - query: comments + args: + post: "{{.value.id}}" + Comment: + fields: + id: + type: Int + required: true + postId: + type: Int + required: true + name: + type: String + required: true + email: + type: String + required: true body: type: String required: true + post: + type: Post + call: + steps: + - query: post + args: + id: "{{.value.postId}}" + Album: + fields: id: type: Int required: true + userId: + type: Int + required: true title: type: String required: true user: type: User - http: - path: /users/{{value.userId}} - userId: + call: + steps: + - query: user + args: + id: "{{.value.userId}}" + photos: + type: Photo + list: true + call: + steps: + - query: photos + args: + album: "{{.value.id}}" + Photo: + fields: + id: type: Int required: true - Query: + albumId: + type: Int + required: true + title: + type: String + required: true + url: + type: String + required: true + thumbnailUrl: + type: String + required: true + album: + type: Album + call: + steps: + - query: album + args: + id: "{{.value.albumId}}" + Todo: fields: - posts: - type: Post - list: true - http: - path: /posts + id: + type: Int + required: true + userId: + type: Int + required: true + title: + type: String + required: true + completed: + type: Boolean + required: true user: type: User - args: - id: - type: Int - required: true - http: - path: /users/{{args.id}} + call: + steps: + - query: user + args: + id: "{{.value.userId}}" User: fields: + id: + type: Int + required: true + name: + type: String + required: true + username: + type: String + required: true email: type: String required: true - id: + address: + type: Address + phone: + type: String + website: + type: String + company: + type: Company + posts: + type: Post + list: true + call: + steps: + - query: posts + args: + user: "{{.value.id}}" + albums: + type: Album + list: true + call: + steps: + - query: albums + args: + user: "{{.value.id}}" + todos: + type: Todo + list: true + call: + steps: + - query: todos + args: + user: "{{.value.id}}" + Address: + fields: + street: + type: String + suite: + type: String + city: + type: String + zipcode: + type: String + geo: + type: Geo + Geo: + fields: + lat: + type: String + lng: + type: String + Company: + fields: + name: + type: String + catchPhrase: + type: String + bs: + type: String + PostInput: + fields: + userId: + type: Int + required: true + title: + type: String + required: true + body: + type: String + required: true + PartialPostInput: + fields: + userId: + type: Int + title: + type: String + body: + type: String + CommentInput: + fields: + postId: type: Int required: true name: type: String required: true - phone: + email: + type: String + required: true + body: + type: String + required: true + AlbumInput: + fields: + userId: + type: Int + required: true + title: + type: String + required: true + PhotoInput: + fields: + albumId: + type: Int + required: true + title: + type: String + required: true + url: + type: String + required: true + thumbnailUrl: type: String + required: true + TodoInput: + fields: + userId: + type: Int + required: true + title: + type: String + required: true + completed: + type: Boolean + required: true + UserInput: + fields: + name: + type: String + required: true username: type: String required: true + email: + type: String + required: true + address: + type: AddressInput + phone: + type: String website: type: String + company: + type: CompanyInput + AddressInput: + fields: + street: + type: String + suite: + type: String + city: + type: String + zipcode: + type: String + geo: + type: GeoInput + GeoInput: + fields: + lat: + type: String + lng: + type: String + CompanyInput: + fields: + name: + type: String + catchPhrase: + type: String + bs: + type: String + ComplexQuery: + fields: + userWithPostsAndComments: + type: UserWithPostsAndComments + args: + userId: + type: Int + required: true + call: + steps: + - query: user + args: + id: "{{.args.userId}}" + - query: posts + args: + user: "{{.value.id}}" + - query: comments + args: + post: "{{.value.posts.0.id}}" + UserWithPostsAndComments: + fields: + user: + type: User + posts: + type: Post + list: true + comments: + type: Comment + list: true From 03a742df484e723f281dcf17fede8c2b20c7c709 Mon Sep 17 00:00:00 2001 From: David Anyatonwu Date: Tue, 27 Aug 2024 20:14:02 +0000 Subject: [PATCH 2/2] fix: tailcall check errors Signed-off-by: David Anyatonwu --- examples/jsonplaceholder.graphql | 10 +++++----- examples/jsonplaceholder.json | 10 +++++----- examples/jsonplaceholder.yml | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/examples/jsonplaceholder.graphql b/examples/jsonplaceholder.graphql index b8c791e2f1..fa3ee6f3fa 100644 --- a/examples/jsonplaceholder.graphql +++ b/examples/jsonplaceholder.graphql @@ -13,23 +13,23 @@ type Query { # Fetch a post by ID post(id: Int!): Post @http(path: "/posts/{{.args.id}}") # Fetch all posts by a specific user - posts(user: Id): [Post] @http(path: "/posts?userId={{.args.user}}") + posts(user: Int!): [Post] @http(path: "/posts?userId={{.args.user}}") # Fetch a comment by ID comment(id: Int!): Comment @http(path: "/comments/{{.args.id}}") # Fetch all comments on a specific post - comments(post: Id): [Comment] @http(path: "/comments?postId={{.args.post}}") + comments(post: Int!): [Comment] @http(path: "/comments?postId={{.args.post}}") # Fetch an album by ID album(id: Int!): Album @http(path: "/albums/{{.args.id}}") # Fetch all albums by a specific user - albums(user: Id): [Album] @http(path: "/albums?userId={{.args.user}}") + albums(user: Int!): [Album] @http(path: "/albums?userId={{.args.user}}") # Fetch a photo by ID photo(id: Int!): Photo @http(path: "/photos/{{.args.id}}") # Fetch all photos in a specific album - photos(album: Id): [Photo] @http(path: "/photos?albumId={{.args.album}}") + photos(album: Int!): [Photo] @http(path: "/photos?albumId={{.args.album}}") # Fetch a todo by ID todo(id: Int!): Todo @http(path: "/todos/{{.args.id}}") # Fetch all todos by a specific user - todos(user: Id): [Todo] @http(path: "/todos?userId={{.args.user}}") + todos(user: Int!): [Todo] @http(path: "/todos?userId={{.args.user}}") # Fetch a user by ID user(id: Int!): User @http(path: "/users/{{.args.id}}") # Fetch all users diff --git a/examples/jsonplaceholder.json b/examples/jsonplaceholder.json index bce0435f18..a8eb3e2442 100644 --- a/examples/jsonplaceholder.json +++ b/examples/jsonplaceholder.json @@ -28,7 +28,7 @@ "type": "Post", "list": true, "args": { - "user": {"type": "Id", "required": true} + "user": {"type": "Int", "required": true} }, "http": { "path": "/posts?userId={{.args.user}}" @@ -47,7 +47,7 @@ "type": "Comment", "list": true, "args": { - "post": {"type": "Id", "required": true} + "post": {"type": "Int", "required": true} }, "http": { "path": "/comments?postId={{.args.post}}" @@ -66,7 +66,7 @@ "type": "Album", "list": true, "args": { - "user": {"type": "Id", "required": true} + "user": {"type": "Int", "required": true} }, "http": { "path": "/albums?userId={{.args.user}}" @@ -85,7 +85,7 @@ "type": "Photo", "list": true, "args": { - "album": {"type": "Id", "required": true} + "album": {"type": "Int", "required": true} }, "http": { "path": "/photos?albumId={{.args.album}}" @@ -104,7 +104,7 @@ "type": "Todo", "list": true, "args": { - "user": {"type": "Id", "required": true} + "user": {"type": "Int", "required": true} }, "http": { "path": "/todos?userId={{.args.user}}" diff --git a/examples/jsonplaceholder.yml b/examples/jsonplaceholder.yml index a75ccf4044..6d196eac88 100644 --- a/examples/jsonplaceholder.yml +++ b/examples/jsonplaceholder.yml @@ -24,7 +24,7 @@ types: list: true args: user: - type: Id + type: Int required: true http: path: /posts?userId={{.args.user}} @@ -41,7 +41,7 @@ types: list: true args: post: - type: Id + type: Int required: true http: path: /comments?postId={{.args.post}} @@ -58,7 +58,7 @@ types: list: true args: user: - type: Id + type: Int required: true http: path: /albums?userId={{.args.user}} @@ -75,7 +75,7 @@ types: list: true args: album: - type: Id + type: Int required: true http: path: /photos?albumId={{.args.album}} @@ -92,7 +92,7 @@ types: list: true args: user: - type: Id + type: Int required: true http: path: /todos?userId={{.args.user}}