simonw / dclient

A client CLI utility for Datasette instances
Apache License 2.0
11 stars 0 forks source link

`dclient get` and `dclient post` commands #5

Open simonw opened 2 years ago

simonw commented 2 years ago

I'm going to implement nicely named commands for all of the key Datasette features, but until I do having utilities for running GET and POST would be handy.

Especially once I add authentication:

simonw commented 2 years ago

For GET:

dclient get https://datasette.io/content/news.json

If you leave off the .json should it add it for you? I think yes.

dclient get https://datasette.io/content/news

For passing query string parameters you can either encode them yourself:

dclient get 'https://datasette.io/content?sql=select+*+from+news'

Or use a -p option:

dclient get https://datasette.io/content -p sql 'select * from news'

Aliases will be resolved as relative URLs, so if you have content as an alias for https://datasette.io/content you can do:

dclient get content

For /content.json

Or:

dclient get content news

To hit /content/news.json

Or if you include a / it will use that from the root of the domain:

dclient get content /content -p sql 'select 1'

Crucially, any authorization token set using the datasette auth command from #3 will be sent automatically.

For POST we need to be able to send JSON. Something like this I think:

dclient post https://simon.datasette.cloud/data/-/create '{
    "table": "name_of_new_table",
    "columns": [
        {
            "name": "id",
            "type": "integer"
        },
        {
            "name": "title",
            "type": "text"
        }
    ],
    "pk": "id"
}'

Or with a registered alias of simon for https://simon.datasette.cloud/data:

dclient post simon /data/-/create '{
    "table": "name_of_new_table",
    ...

Here's a problem: I thought this could work:

dclient post simon /-/create '{...}'

But how would the tool know which of the following URLs should be constructed in that case?

I think the / meaning "from the top of the domain" idea is a bad one. It should always be added on starting at the /simon URL prefix.

simonw commented 2 years ago

I don't like the bit where it adds .json for you - I think that's too confusing. The other commands (dclient rows alias tablename etc) already help with URL construction, no need to make the get and post commands more confusing than they need to be.

simonw commented 2 years ago

So:

dclient get content /news.json

And:

dclient get content '.json?sql=select+5'

That second one feels a bit weird though. Not fully convinced about that yet.

Actually no: adding .json makes no sense because the user may want to fetch .csv or even something added by an output renderer plugin like .yaml.

simonw commented 2 years ago

Maybe dclient alias add should validate URLs and reject them if they end in a / or don't correctly resolve to a database path?

I could use the presence of this header to help there:

~ % curl -i https://datasette.io/content
HTTP/2 200 
link: https://datasette.io/content.json; rel="alternate"; type="application/json+datasette"
simonw commented 2 years ago

I could also use the presence of that header in any client call - I could say "if the user accidentally fetches back HTML but the HTML has a rel="alternate"; type="application/json+datasette" then resolve that instead.

This is much nicer than adding .json to things randomly, and is in the spirit of why I implemented that link: header in the first place.