mistweaverco / kulala.nvim

A minimal 🤏 HTTP-client 🐼 interface 🖥️ for Neovim ❤️.
https://kulala.mwco.app
MIT License
192 stars 4 forks source link

[Suggestion] More jq integration #4

Open tdroxler opened 1 week ago

tdroxler commented 1 week ago

Thx for the nice plugin, looks super good.

While I was trying it I thought it would be awesome to have a nice way to pipe multiple curl and jq.

Typically I usually do long sequence like the following when I want to get a specific value from my API:

curl -s 'https://node.mainnet.alephium.org/blockflow/chain-info?fromGroup=0&toGroup=0' | \
jq '.currentHeight' | \
xargs -I{} curl -s 'https://node.mainnet.alephium.org/blockflow/hashes?fromGroup=0&toGroup=0&height={}' | \
jq -r '.headers .[]' | \
xargs -I{} curl -s  'https://node.mainnet.alephium.org/blockflow/blocks/{}' | \
jq '.timestamp' 

I then store them in some bash scripts, but would be nice to have everything nicely stored in an http file.

gorillamoe commented 1 week ago

That's a really good suggestion! I have to think about the best way to implement it, but maybe something like a .http files with multiple request blocks could work, then something like a require('kulala').run_all() command. I have to think about the scripting thing, but I guess that could work :+1:

gorillamoe commented 1 week ago

I think the easiest thing without breaking the spec and doing too much custom stuff/magic would be something like this:

GET https://node.mainnet.alephium.org/blockflow/chain-info?fromGroup=0&toGroup=0
accept: application/json

###

GET https://node.mainnet.alephium.org/blockflow/hashes?fromGroup=0&toGroup=0&height={{$previousResponse.body.currentHeight}}
accept: application/json

###

GET https://node.mainnet.alephium.org/blockflow/blocks/{{$previousResponse.body.headers}}
accept: application/json

###

GET https://client.local/previousResponse.body.timestamp
accept: application/json
custom-internal: true

The magic part is just the extraction of the previousResponses and the dummy request at the end that needs to be intercepted by the client in this case kulala.

I would need to implement the said things and also have a require('kulala').run_chain() function exposed.

I think that could work quite beautifully and doesn't really break the spec.

What do you think?

Myhed commented 1 week ago

That is a good thing in my case and another things i thought is to select in visual mode what chains requests to exec in http file,

In my opinion that can be done by get the ranges lines instead scanning all http file.

tell me if i am wrong

gorillamoe commented 1 week ago

I have this running as a POC in two different ways, the one I described here first, I dislike most now. It's not flexible enough.

The other one I like most is somehow broken, because I heavily rely on the Treesitter HTTP Grammar, and that is broken and I can't easily fix that, because I don't have access to that repo. That would be also a back and forth for every bug I encounter in the HTTP Grammar.

I decided for the approach of completely rewriting the Kulala Parser without Treesitter (you can always use the TS HTTP Grammar for Syntax Highlights, but these seem off too, when it's broken).

When I say broken, I don't mean to be mean, just that we're conforming to the spec, but the Treesitter Grammar errors.

I also plan to ship http syntax highlights in the coming weeks, so that the highlights are not off by quite a bit, when TS throws errors.

The current POC that is working when TS does not throw is this:

GET https://node.mainnet.alephium.org/blockflow/chain-info?fromGroup=0&toGroup=0
accept: application/json
http-client-pipe: jq .currentHeight

###

GET https://node.mainnet.alephium.org/blockflow/hashes?fromGroup=0&toGroup=0&height={{$previousResponseBody}}
accept: application/json
http-client-pipe: jq .headers .[]

###

GET https://node.mainnet.alephium.org/blockflow/blocks/{{$previousResponseBody}}
accept: application/json
http-client-pipe: jq .timestamp

When you pass a http-client-* header the header is treated a special http-client header that tells the http-client in this kulala to do some magic.

In the first iteration the headers were called kulala-, but then I thought that it might be good to have them be generic, so that we can open up pull requests to the vscode rest-client and others, once we got this working.

When you pass the specific http-client-pipe header command you end up telling kulala that it should not take the response as is, but rather pipe it through an external program and then show the response.

The magic variable $previouseResponseBody holds the response of the previous response body, so that would be the piped output.

This way we're flexible as hell and conform somehow to the spec, at least when it comes to the grammar or syntax of the file.

In my opinion that can be done by get the ranges lines instead scanning all http file.

With the rewrite of the parser, I need (in another rewrite that might change, because I don't really NEED, but it makes things easier) to scan the whole http file, as I would with the HTTP file, but then we could run only the selected chained commands, that's right.

Any thoughts on this?

huantrinh1802 commented 4 days ago

This sounds like a good approach imo. One thing I would change is instead of using $previousResponseBody, we can use name the requests like


# @name=chainInfo
GET https://node.mainnet.alephium.org/blockflow/chain-info?fromGroup=0&toGroup=0
accept: application/json

###
# @ref=chainInfo
# @name=hashReq
GET https://node.mainnet.alephium.org/blockflow/hashes?fromGroup=0&toGroup=0&height={{$chainInfo.body}}
accept: application/json

The idea is from HttpYac Metadata