jointoucan / finch-graphql Goto Github PK
View Code? Open in Web Editor NEWLocal GraphQL API in the background process of a web extension.
Home Page: https://jointoucan.github.io/finch-graphql/
License: MIT License
Local GraphQL API in the background process of a web extension.
Home Page: https://jointoucan.github.io/finch-graphql/
License: MIT License
I kinda want to do this for the client v. the background scripts to have a more clear separation. Right now it gets kinda weird including react
in the client. Think moving to Lerna could be a cool fix to this.
- packages
- background
- client
- react
- devtools
- codegen
- testing-utils
Of course, this is a bit verbose but could be awesome to at least as the capability to expand to this.
This should be configurable via the query
method and useQuery
hook. This will make it so we can extend the timeout of specific calls just in case they are going back and forth with the server.
This will allow us to do things like responding to queries with cache if the cache is available and then update the cache after already responding.
When there is an error in the background process of the extension, the error message is an empty object. I think this is because the background process of the other extension is there and potentially consuming events, but I assume not responding with anything good.
Let's see if we can catch this case and allow the client to resolve a better error message in the errors.
This would be useful if we want to potentially send a deferred message to the tab after some work has been done without having to wait for a response.
This happens where there is something that is refreshing the background page and we are losing the connection. There should be some type of retry connection with the extension background.
Install the new version and wanted to take advantage of the new polling mechanism, ended up running into issues using the codegen hooks, but the regular hooks worked fine.
To support multiple vendors ( Chrome, Firefox, Edge, or Safari ) you would need to handle multiple ids for this to work with external messaging. You could do something like user-agent sniffing to get the correct vendor and send the specific id but it would be nicer if there was a way to scan for active ids. This could be something like passing a list of ids to finches context.
<ExtensionProvider scanIds={[x,y,z]}>...</ExtensionProvider>
The extension provider will make a built-in query to a finch API.
query healthcheck {
_healthcheck
}
Then when something responds to this we could store some state into the provider that extension is responding to queries.
Think there could be weird issues when multiple respond probably not terrible though.
I am not quite sure how to support this yet, but it looks like there are a few main things to do.
We will need to update codegen to create the subscription hooks, and I assume we will want to setup the port stuff internally. I think the code in the devtools to connect a port is pretty good for this.
I would like also to have some type of support for this in the devtools. Not sure on what that can look like, but I assume it will probably a list of responses from the subscription.
This happens because the id for the request or not very good we should probably use UUID for this instance.
Right now we run into an issue of externally_connectable
not working on Safari, and Firefox. This is a great way to connect to websites without having to inject a script onto the page. Seems like we will need to work-around this by injecting a script into the page and interfacing with that script.
We need to update the client scripts to detect if externally connectable is supported or not. Seems like the API just will not be present if that is the case. Then we need to start sending messages through the document.
Something like
const sendExternalMessage = (query, variables) => {
const requestedId = uuid.v4()
var storeEvent = new CustomEvent('message-key:request', { query, variables });
return new Promise((resolve, reject) => {
document.dispatchEvent(storeEvent);
document.addEventListener(() => {
// wait for response
})
})
}
sendDataToExtension("hello", "world");
Then we need an extension side that will essentially proxy these document events into actual messages to the background script.
I think the only difference here is we may want to maintain a list of externally connectable. This will help us from allowing everything to be externally connectable.
The interesting thing here is that we almost set up a way for the externally connectable list to be more dynamic without having to add it to the manifest. This probably can be a bad thing as well in terms of security.
We will probably need some extensive documentation about this. On how to setup for best results.
This is a pretty powerful API, we currently use it to show a list of extensions but we can also use it to be able to show if the extension is enabled or disabled using this info.
If it seems like something that users would like we could even enable the extension from that page using the browser.management.setEnabled
method.
I am doing some performance work, and my brain got thinking around how the messages panel works in the dev tools. Currently, the timing is based.
Messaged received in background -> message response sent.
It would be nice to be able to potentially see any IPC time even though it should be tiny. It would be interesting to be able to get a more full timing of messaging especially if there are potential issues with the background process that is making it not accept connections right away. So now timing would be.
Message sent -> Messaged received in background -> message response sent.
Message sent to message received would represent time spent in IPC.
We heavily restrict places the extension can be called but it would be great to turn of introspection on production.
I think it would be nice to add some instructions around codegen, and testing to make this easier to set up for a project.
If a function is passed to the context I would expect to be able to access all the values available in a context like sent. I think currently that function is only called once initial on startup of the api
I set up a new project with Finch today and it was a little difficult. I feel like it would be much easier to be able to look at a boilerplate and get examples or potentially scaffold an entire project.
I would like to get this project set up for success with v3 extensions. I have run into quite a few issues trying to convert it to a v3 extension.
webextension-toolbox currently does not support v3 of Chrome extensions. This is due to manifest validation failing due to background.service_worker key. Also, the Webpack plugin tries to append another background script that allows for reloading.
Validation is a pretty easy fix. The other fix would mean this plugin would need to change how they inject their scripts into the background page. Could be possible to polyfill it.
Solution
Quite a few issues to patch with this one... potentially we need to start looking at new candidates for building the dev tools extension. Maybe, web-ext or a homegrown solution.
Right now Chrome requires the background script to be on the same level as the manifest. Chrome 93 fixes the issue. I also wrapped the background script as recommended here, and everything started up fine.
Solution
We might want to wait out till Chrome 93 comes out which looks like it will come out August 31st.
The devtools uses a pretty common polyfill webextension-polyfill. This polyfill when put through Webpack seems to be adding some additional calls to window
which will not work in service workers. Here is the line and I locally modified it to use this
instead of window.
Everything works after that, glad to see the core of finch-graphql
still works in v3.
We added in some new reconnection of the port functionality and we should document it more.
Right now you have to set up a custom logger around the onMessage stuff to achieve this. I think it would be much better if there was a hook that we could pass as an option when creating an instance that sets up a logger. This should make it work for both normal messages and external messages as well.
I was wanting to use to dogfood finch in this instance but I think the way current messages works does not work well for what we are trying to do with message tabs.
The biggest issue is that we base the messages on polling, and the extension holding onto a small amount of cache. Once the dev tools extension polls for the messages of the extensions it will essentially pull that cache and remove it from the extension.
The first issue is that if there are two instances of Finch GraphiQL polling these messages it means that there is a good chance the extension will only get partial messages because one of the extension instances may be getting a majority of the cache and clearing it from the others.
The second issue is that this barrage of messages is probably not great for the perf of the extension. I have not seen too much slowdown that I can attribute to this issue, but I assume it will probably be happenings.
This is probably just me being lazy with the initial implementation but in this instance, once the dev tools open the polling starts. This might be a combo on how chakra-ui tabs work, but sure there is a hook we can use to know if the tab is open. We should probably only record when the tab is open to avoid any unwanted polling.
Message tabs should move to a port
implementation so that way we can push to the dev tools. This change alone gets rid of polling and the issue of storing cache. It also allows us to potentially send multiple messages per each request. We can eventually do timing and not show requests after response, and actually show them based on when they initially get sent.
This makes it super simple to know when you should be receiving messages. I think the initial open will start recording but we should also have a way to turn off the recording. Also, it would be nice once the recording is started it will persist between tabs. Until turned off or the extension is closed.
This is probably going to affect Toucan, but if we do not handle connections super well we have the potential to create targets that going to be getting random information. This should be on a list of breaking changes for finch-graphql
once published.
Seems like the new types for browser might be pretty aggressive, and effecting types of installed extensions.
We need to update the readme docs or remove them and rely on the site more.
Just makes it easier to collab.
Seems like there are issues right now with the settings tab of the extension. When trying to paste in an extension id you get this weird [Object Object]
string then the string is not updatable.
If you want to use the management API, it seems like that only starts working after restarting a few times. It just shows the button with no feedback.
Seems like our cache is pretty sticky in the hook, and will not clear out an error, once its resolved. We ran into an error with this when trying to get Firefox working and dealing with the external messaging script. Essentially we would poll and get errors because the script was not ready. Once the script was ready we got back data but the error persisted.
I keep getting this issue not sure if its because of the setup in another extension of a issue with the library but it has been persistent and I have not been able to figure out the issue.
Uncaught Error: Cannot use GraphQLObjectType "Query" from another module or realm.
Ensure that there is only one instance of "graphql" in the node_modules
directory. If different versions of "graphql" are the dependencies of other
relied on modules, use "resolutions" to ensure only one version is installed.
https://yarnpkg.com/en/docs/selective-version-resolutions
Duplicate "graphql" modules cannot be used at the same time since different
versions may have different capabilities and behavior. The data from one
version used in the function from another could produce confusing and
spurious results.
at instanceOf (instanceOf.js:29)
at isObjectType (definition.js:138)
at mapArguments (index.mjs:3156)
at mapDefaultValues (index.mjs:3037)
at Module.mapSchema (index.mjs:2953)
at createNewSchemaWithResolvers (index.js:325)
at addResolversToSchema (index.js:218)
at addMiddlewareToSchema (middleware.mjs:11)
at normalisedMiddlewares.reduceRight.schema.schema (middleware.mjs:40)
at Array.reduceRight (<anonymous>)
I have already added resolutions to the package, and also confirmed that I only have one version of graphql installed.
Found this library we might be able to hooks this up to the messages for a neat timeline component.
https://github.com/namespace-ee/react-calendar-timeline
edit: library uses moment as peer dependency
It would be nice to be able to put Finch dev tools in an electron app. Right now the dev tools only work for Chrome, but the support library is now starting to support a wide array of different Platforms: Safari, Safari iOS, Firefox, Edge, Opera, and Chrome. It would be extremely beneficial if we were able to support more of those platforms. To do this we need to rethink how the dev tools communicate with the library.
Right now we make an external communication between two extensions, this is an API that is only supported in Chrome. This is largely why the support for the dev tools only works on Chrome. We would need to change this behavior to allow for WS connections to support something like an electron app, and with Safari I think we would need secure web sockets...
We should start evaluating what this looks like, what is the cost, and can we possibly support something like Safari with these devtools?
There might be other solutions to this, just it seems like Safari is the best bet.
Right now we have a custom hook to add additional logging. I think this is fine but I think a more eloquent solution could be to use some sort of Middleware like outlined in this article.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.