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

Proposal: Breaking GraphiQL APIs & New APIs 💥 -> 🚀 #1165

Open
acao opened this issue Dec 26, 2019 · 6 comments
Open

Proposal: Breaking GraphiQL APIs & New APIs 💥 -> 🚀 #1165

acao opened this issue Dec 26, 2019 · 6 comments

Comments

@acao
Copy link
Member

acao commented Dec 26, 2019

NOTE: most important detail is what we are keeping, and that is almost all of the GraphiQL props

1. GraphQL.state

(e.g. GraphiQL.state.query) is being accessed directly, and is advertised somewhat as a public interface in the Readme and has been for some time. However, our move to context means that providers will contain state. Also there will be multiple queries with multple tabs! Also if I'm not mistaken it's not really reccomended to access Component state directly like that?

replacement proposal:

const { query } = GraphiQL.state

becomes

const { operation } = useOperationContext({ tabId: 0 })

and this one which will require the parent workspace context to work (i.e. a tab plugin, etc), and already know which is the active tab by default from parent workspace context.

const { operation } = useOperationContext()

also for non-hooks class component style, they can still in a tab plugin use:

 <OperationContext.Consumer>{({ operation }) => ()}</OperationContext.Consumer>

2. GraphiQL.methods()

There are also Component methods that are used to access values, submit queries programatically, and for many other purposes in the wild.

  • `onEditQuery'

These also will move to context provider, possibly just dispatch actions with types that pass args mapped to some of the same and some new method names.

then you can readily dispatch actions via a similar interface:

const = { operation, setOperation } = useOperationContext({ tabId: 'current' })

return (
  <textarea onChange={e => setOperation(e.target.value)}></textarea>
)

also in a panel/tab context:

 <OperationContext.Consumer>{({ setOperation }) => ()}</OperationContext.Consumer>

a better approach with useGraphiQLReducers()

import { useGraphiQLReducers, Actions } from 'graphiql'

function ASTReducer(action, state) {
  switch(action.type) {
    case [Actions.onOperationChange]: {
       state.operationAST = parse(state.operations.get(action.tabId));
       return state
     }
     default {
       return state
     }
  }
}

useGraphiQLReducers({
   init: () => { operations: new Map(['mutation SendMsg{ send(msg:"hello!"){response} }']),
   reducers: [ASTReducer]
})

hopefully we can figure out how to provide side effects for actions in useGraphiQLReducers as well?

the GraphiQL.methods() interfaces are also accessible outside of a bundler for react JSX (Parcel, Webpack, Rollup, etc). this new proposal however would require one of these bundlers to achieve these kinds of capabilities. You can also use React.createElement directly with the contexts we will export to avoid that, but that might grow cumbersome

3: GraphiQL.Logo and friends

These are a cute interface but they will be deprecated soon for new patterns for defining your own layouts for the workspace and operation editor panes layout per tab, and replacing components programatically in ways that will be provided by plugins.

Also, @walaura is plugging away at a new theme provider and baseline theme and components that we will begin to adopt into our component tree and you will be able to override the theme defaults and style at the props level, again a prototypical interface over plugins.

Summary

All of these interface will need to be dropped so we can make way for the first proto-plugin features, which will be defining custom components that inherit workspace/operation tab context that you can pass from the GraphiQL component, and will be rendered either in the left or right panes, and will optionally have an icon in the icon bar and labels and such.

These will expose the above mentioned capabilities, and none of this requires a plugin layer yet, and these interfaces should hopefully be close to what the plugin interfaces will be for RC. hooray react for making it so easy to create extensible components!

The way we pass these early "plugins" to GraphiQL will be at the props level, maybe in a plugins array. Eventually you'll be able to use graphql config to provide predefined plugins with their own settings overrides in graphql "presets" that you build with webpack, and eventually hopefuly the ability to search, select and install/uninstall/disable etc plugins over the wire! not as far off as it might seem!

Notes:

  • I'm tempted to start renaming "query" to operation, unless it refers to a query operation, in the codebase. i think i will start discussion issues for all these topics
  • the above examples are just psuedocode and still has yet to be proofed, just meant to get the conversation started on what it could look like. working group calls very soon!

Related Issues:

@acao acao changed the title GraphiQL Discussion: Breaking API Changes & New Interfaces 💥 -> 🚀 GraphiQL Discussion: Breaking API Changes & New APIs 💥 -> 🚀 Dec 26, 2019
@acao acao pinned this issue Dec 26, 2019
@acao acao changed the title GraphiQL Discussion: Breaking API Changes & New APIs 💥 -> 🚀 Discussion: Breaking GraphiQL APIs & New APIs 💥 -> 🚀 Dec 27, 2019
@acao acao changed the title Discussion: Breaking GraphiQL APIs & New APIs 💥 -> 🚀 Proposal: Breaking GraphiQL APIs & New APIs 💥 -> 🚀 Dec 27, 2019
@orta
Copy link
Member

orta commented Dec 29, 2019

Feels fine to break these considering the extra opportunities the plugin system offers instead of these

@iFlameing
Copy link
Contributor

@acao can you give me some starter point regarding #828. As you mentioned we can do it using reducer. I already read the conversation regarding plugin in #829 and really excited about this feature.

@acao
Copy link
Member Author

acao commented Feb 21, 2020

awesome yes! i think in the case of prettifying it's unique because of monaco, so for that we will use monaco's API directly.

here's an example of how i envisioned the prettier plugin looking:
https://github.com/acao/graphiql-1-poc-monaco/blob/master/src/plugins/graphiql-plugin-formatter-prettier/PrettierFormatterPlugin.tsx

as you can see theres a way monaco wants you to set up the formatting provider, so while it would make sense via a reducer, this is the proper monaco way to do it, so that it works with the editor shortcuts and the core monaco formatting handlers.

@acao
Copy link
Member Author

acao commented May 20, 2020

@elvin666666 anything you are looking to refer to here? any questions?

@acao acao unpinned this issue Jul 15, 2020
@amanprateek123
Copy link

@acao Good evening sir, I want to contribute in open source. So can you give me some issues to work on it(related to GraphiQL plugins or redesigning layout).

@amanprateek123
Copy link

@acao Sir, can I work on the following issues : #829, #978? If not, please suggest some other related issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
@orta @acao @iFlameing @amanprateek123 and others