-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implements fetch for readme file of glues #143
base: master
Are you sure you want to change the base?
Changes from 9 commits
d6b0a5f
266afdc
5253cd1
bcaf545
04714d5
3a53927
a574eab
c1115e4
26c6004
4afb5ea
43e4f12
ccabcfc
0054d22
f8d1eb6
76f2eae
faae10d
bafcb28
fbd3b9c
3f1bd48
355487f
bd23617
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,245 +1,11 @@ | ||
--- | ||
id: herbs2gql | ||
title: GraphQL - Herbs2GQL | ||
sidebar_label: GraphQL | ||
slug: /glues/herbs2gql | ||
hide_title: true | ||
--- | ||
|
||
Creates GraphQL types (queries, mutations, etc.) based on herbs [entities](/docs/entity/getting-started) and [usecases](/docs/usecase/getting-started), based on [Apollo](https://www.apollographql.com/) GraphQL. | ||
import ReadMeDoc from '../../src/components/ReadMeDoc' | ||
|
||
<ReadMeDoc docURL='https://raw.githubusercontent.com/herbsjs/herbs2gql/master/README.md'/> | ||
|
||
## Getting started | ||
### Installing | ||
```bash | ||
$ npm install @herbsjs/herbs2gql | ||
``` | ||
### Using | ||
If your project uses [Herbarium](https://github.com/herbsjs/herbarium) as discovery service you can generate mutations, queries and types with less code. | ||
|
||
```javascript | ||
const { herbarium } = require('@herbsjs/herbarium') | ||
const { herbs2gql } = require('@herbsjs/herbs2gql') | ||
|
||
const { mutations, queries, types } = herbs2gql(herbarium) | ||
``` | ||
|
||
|
||
## Advanced Features | ||
|
||
All methods returns a string in GraphQL format representing the type based ([gql](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#gql)) and a [resolver](https://www.apollographql.com/docs/apollo-server/data/resolvers/) (when expected). | ||
|
||
``` js | ||
const { entity, field, id } = require('@herbsjs/herbs') | ||
const { entity2type } = require('@herbsjs/herbs2gql') | ||
|
||
const user = entity('User', { | ||
id: id(String), | ||
name: field(String), | ||
document: field(String), | ||
age: field(Number), | ||
active: field(Boolean), | ||
}) | ||
|
||
const gql = entity2type(user) | ||
console.log(gql) | ||
/* Result | ||
type User { | ||
id: String | ||
name: String | ||
document: String | ||
age: Float | ||
active: Boolean | ||
} | ||
*/ | ||
``` | ||
|
||
### GraphQL Type | ||
|
||
To convert a Herbs Entity to GraphQL Type: | ||
|
||
```javascript | ||
const entity = entity('User', { | ||
id: id(String), | ||
name: field(String), | ||
document: field(String), | ||
age: field(Number), | ||
active: field(Boolean), | ||
}) | ||
|
||
const gql = entity2type(entity) | ||
``` | ||
|
||
### GraphQL Input | ||
|
||
To convert a Herbs Entity to GraphQL Input: | ||
|
||
```javascript | ||
const entity = entity('UserFilter', { | ||
name: field(String), | ||
age: field(Number), | ||
}) | ||
|
||
const gql = entity2input(entity) | ||
``` | ||
|
||
### GraphQL Query | ||
|
||
To convert a Herbs Use Case to GraphQL Query: | ||
|
||
```javascript | ||
const usecase = usecase('Get User', { | ||
request: { | ||
id: Number, | ||
document: String | ||
}, | ||
|
||
response: User | ||
}) | ||
|
||
const resolverFunc = (parent, args, context, info) => { } | ||
|
||
const [gql, resolver] = usecase2query(usecase, resolverFunc) | ||
``` | ||
|
||
### GraphQL Mutation | ||
|
||
To convert a Herbs Use Case to GraphQL Mutation: | ||
|
||
```javascript | ||
const usecase = usecase('Update User', { | ||
request: { | ||
id: Number, | ||
name: String, | ||
age: Number, | ||
active: Boolean | ||
}, | ||
|
||
response: User | ||
}) | ||
|
||
const resolverFunc = (parent, args, context, info) => { } | ||
|
||
const [gql, resolver] = usecase2mutation(usecase, resolverFunc) | ||
``` | ||
|
||
### GraphQL Subscription | ||
|
||
To convert a Herbs Use Case to GraphQL Subscription: | ||
|
||
```javascript | ||
const usecase = usecase('New User Notification', { | ||
request: { | ||
id: Number, | ||
}, | ||
|
||
response: UserMessage | ||
}) | ||
|
||
const resolverFunc = () => { } | ||
|
||
const [gql, resolver] = usecase2subscription(usecase, resolverFunc) | ||
``` | ||
|
||
|
||
### Custom Names or Conventions | ||
In Herbs it is possible to include personalized names for queries, mutations, inputs and types | ||
custom names are always prioritized | ||
|
||
#### Custom Names | ||
|
||
```javascript | ||
const options = { inputName: 'An-Entity' } | ||
|
||
// for entity2input | ||
const gql = entity2input(givenAnInput, options) | ||
|
||
// for entity2type | ||
const gql = entity2type(givenAnEntity, options) | ||
|
||
//for mutation, query or subscription example using mutation | ||
const [gql, resolver] = usecase2mutation(givenAUseCase, resolverFunc, options) | ||
``` | ||
|
||
#### Conventions | ||
At the convention, a function must be sent, it must return a text formatted according to the sended convention | ||
```javascript | ||
const options = { convention: { inputNameRule: (str) => `snake_case_returned` }} | ||
|
||
// for entity2input | ||
const gql = entity2input(givenAnInput, options) | ||
|
||
// for entity2type | ||
const gql = entity2type(givenAnEntity, options) | ||
|
||
//for mutation, query or subscription example using mutation | ||
const [gql, resolver] = usecase2mutation(givenAUseCase, resolverFunc, options) | ||
``` | ||
|
||
### Apollo Errors and Err | ||
|
||
`herbs2gql` deals with errors in the default resolver. It translates the usecase's errors into graphql errors: | ||
|
||
| Usecase Error | Apollo Error | | ||
|--------------------------|----------------| | ||
| Permission Denied | ForbiddenError | | ||
| Not Found | ApolloError | | ||
| Already Exists | ApolloError | | ||
| Unknown | ApolloError | | ||
| Invalid Arguments | UserInputError | | ||
| Invalid Entity | UserInputError | | ||
| Any other kind of errors | UserInputError | | ||
|
||
However, it's behavior can be overridden in the `errorHandler` property of the options parameter: | ||
|
||
```javascript | ||
const { defaultResolver } = require("@herbsjs/herbs2gql") | ||
|
||
const myCustomErrorHandler = (usecaseResponse) => { | ||
// handle the errors on your own way | ||
} | ||
|
||
const options = { | ||
errorHandler: myCustomErrorHandler, | ||
} | ||
|
||
const updateUser = usecase("Update User", { | ||
// usecase implementation | ||
}) | ||
|
||
const [gql, resolver] = usecase2mutation( | ||
updateUser(), | ||
defaultResolver(updateUser, options) | ||
) | ||
``` | ||
|
||
Your custom error handler can also utilize the `defaultErrorHandler` as a fallback: | ||
|
||
```javascript | ||
const { defaultResolver, defaultErrorHandler } = require("@herbsjs/herbs2gql") | ||
|
||
const myCustomErrorHandler = (usecaseResponse) => { | ||
// handle the errors on your own way | ||
|
||
// use the default error handler when there is no need of a specific treatment | ||
return defaultErrorHandler(usecaseResponse) | ||
} | ||
|
||
const options = { | ||
errorHandler: myCustomErrorHandler, | ||
} | ||
|
||
const updateUser = usecase("Update User", { | ||
// usecase implementation | ||
}) | ||
|
||
const [gql, resolver] = usecase2mutation( | ||
updateUser(), | ||
defaultResolver(updateUser, options) | ||
) | ||
``` | ||
|
||
The [Known Errors](/docs/usecase/result#known-errors) are described in the documentation. | ||
|
||
#### Example | ||
|
||
Additionally you can view a simple demo application of this library in [todolist-on-herbs](https://github.com/herbsjs/todolist-on-herbs). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React, { useEffect, useState } from 'react' | ||
import ReactMarkdown from 'react-markdown' | ||
|
||
export default function ReadMeDoc({ docURL }) { | ||
const [markdown, setMarkdown] = useState('') | ||
|
||
useEffect(() => { | ||
fetch(docURL) | ||
.then((res) => res.text()) | ||
.then((text) => setMarkdown(text)) | ||
}, []) | ||
|
||
return ( | ||
<> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this indentation is correct? It looks so long |
||
<ReactMarkdown children={markdown} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens if url is unavailable or broken? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point! |
||
</> | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be inside a env file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn´t able to put it inside the md file, but I put the base URL inside the env file to import it at the react component and oly pass the endpoint at the md file.