Skip to content
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

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 3 additions & 237 deletions docs/glues/herbs2gql.md
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'/>
Copy link
Contributor

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

Copy link
Contributor

@juliadibo juliadibo Jul 28, 2022

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.


## 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).
2 changes: 1 addition & 1 deletion docs/glues/herbsshelf.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ And call the shelf into you prefered rest route

### Example

You can see Herbs Shelf in action in the [To Do List On Herbs](https://github.com/herbsjs/todolist-on-herbs) project.
You can see Herbs Shelf in action in the [To Do List On Herbs](https://github.com/herbsjs/todolist-on-herbs) project.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"node-fetch": "^3.2.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-live": "2.2.3"
"react-live": "2.2.3",
"react-markdown": "^8.0.3"
},
"browserslist": {
"production": [
Expand Down
18 changes: 18 additions & 0 deletions src/components/ReadMeDoc.js
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 (
<>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this indentation is correct? It looks so long

<ReactMarkdown children={markdown} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if url is unavailable or broken?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!
Just implemented a catch with an Error message, asking to go to github doc instead.

</>
)
}