tink: Implement tink view


(Kat Marchán) #1

I’ve marked this as a good first patch because it’s fairly straightforward, but I’m keeping this in a separate topic from tink: Implement ancillary subcommands because, like tink: New search UI, this is going to take a bit more than the smaller commands to implement. If you’re interested in doing this, please reply below and claim it!

I’d like to have a tink view command that works like npm@6's npm view <pkg> command. The main difference is that I’d like a similar interface implemented on top of ink, which is the UI library I’d like to use for various interactive features in tink. The end result should be not only a standalone command, but a standalone ink component that can be injected into other commands, since I’d like to have this displayed by the new search command.

The new tink view should also support a --json version, as well as the same sort of field-filtering that regular npm view supports. Please refer to the current npm view code, which is admittedly a bit of a mess, as one of npm’s oldest commands.

For reference, this is what a regular npm view looks like right now, as of npm@6.4.1:

tink: New search UI
(Lars Willighagen) #2

Claimed by @larsgw:

(Lars Willighagen) #3

I see tink doesn’t work on node 8? I’ll see if I can upgrade…

(Kat Marchán) #4

It does not. I’m targeting node@>=10 for the time being. Because I’m manually patching fs and module, I need to be fairly specific until there’s a system of supporting multiple versions over time.

(Lars Willighagen) #5

Okay, luckily n seems to be working just fine so that’s all sorted then.

(Lars Willighagen) #6

First draft:

I copied the style and content from npm view, apart from some color changes. Also, I didn’t use any JSX yet, because I wasn’t sure how you wanted the build steps to be. Here’s the patch (so far):

The --json API is also available, the main (only) difference with npm view being that single fields are JSON.stringifyed too, for consistency. It, as promised, also exports a number of ink components:

  • PackageView: as shown above
    • pkg: part of packument (the version). Some info from the complete packument has to be copied to the part for now
  • PackageFields: list fields
    • pkg: part of packument
    • fields: fields that should be listed
    • prefixVersion: prefix the spec (if multiple PackageFields are put after eachother)
    • prefixFields: if multiple fields are requested (will be removed)
  • PackageField: value prefixed with field name
    • same as PackageValue
  • PackageValue
    • field: field name/path (including dots)
    • value: resolved value
    • props: for object values, list what props to show and in what order
    • maxProps: maximum number of props to show (ignored if props is passed)

Some of those components can definitely be improved, and will be later. Feedback welcome, both on the components and everything else.

tink: New search UI
(Kat Marchán) #7

oh yes, please don’t use any JSX yet. It’s straightforward enough without. :slight_smile:

(Kat Marchán) #8

Holy crap this is so cool. These are gonna be so useful!

My only suggestion is that instead of passing in the version itself, have PackageView take the entire packument, plug a spec that will be used to select the one to display (default latest). I think that’ll make it more usable across the board, since everything just works off packuments, pretty much. The other thing is that it’d be nice to replicate the columned display of the dependencies section, which seems different? Maybe it’s just because it’s a different column component?

The rest, I think, looks good for now. There’s so much code! You rock!

(Lars Willighagen) #9

The main reason I didn’t is because then either code would be duplicated or the --json API would have to go through Ink too, but I have an idea for that.

Agreed, copying those variables is

  1. annoying and
  2. it also changes the output JSON

so I’ll definitely work on that.

There’s no column component that I know of, but I’ll look into using process.stdout.{columns,rows}. This issue showed up when googling too (and addresses the trailing newline stuff as well), and links to react-blessed which looks cool as well.

I see there are some other interesting components such as Indent and maybe Text that I should be using.

(Kat Marchán) #10

You mean like… have the component accept a json option and render as JSON? 'cause that’d be A+

You can just wrap cli-columns with a component, I think. That’d be just fine. I think?

(Lars Willighagen) #11

Oh… kay. Okay. That works too then, I guess. :slight_smile:

Probably not if it has to work on other components… I could (and wouldn’t mind to) change the PackageValue implementation to not use components (but the chalk API directly), but then I’d have to implement indentation myself, right after I discovered there’s a plugin for that. Apart from that, PackageValue is the lowest-level public component, so that should be fine.

(Kat Marchán) #12

My main concern with using blessed or anything based on it is that it’s a very large library. I was hoping that by using ink, we’d take a small file size hit in exchange for being able to incrementally add components only as-needed.

How are you feeling about Ink so far, by the way? Part of this exercise is to get a sense of how easy it might be to work with and whether it’s worth switching to wholesale.

(Lars Willighagen) #13

Right, makes sense. The gifs look cool tho.

Ink itself is okay, I suppose. However, I don’t get to play around with interactive stuff, and for general layout it’s a lot of components and whitespace & inline/block mess (just like CSS lol) for something that could be done with a few utility functions, it seems. I’m getting new ideas on how to solve that while writing this, so all is probably well. For interactive stuff, I can imagine this being the best solution for the least amount of bytes.

(Kat Marchán) #14

Yeah, I think the view component is a good example of something that’s much better off getting rendered directly instead of interactively, if it weren’t for wanting to reuse it within tink search, which will be very interactive. I expect it’ll absolutely shine there, but thanks for doing the guinea pig thing so far :smiley:

(Kat Marchán) #15

As per this reply on tink: New search UI, I believe I’ve fixed an issue with the JSX rendering for tink sources so… you should be able to rename your command to view.jsx and use JSX instead of h().

(Lars Willighagen) #16

Works (mostly*), great!

* whatever parser is used, it doesn’t like let {a = 4} = this.props

tink: New search UI
(Lars Willighagen) #17

Second try. Looks mostly the same, so no screenshot. I don’t have the columns yet, but the components are probably pretty useful for @chrisforrette. New component APIs:

  • PackageView:
    • packument
    • spec: display versions matching SemVer version or range (edit: or tag)
    • json: output JSON
  • PackageFields: list fields (change: now always prefixes field name)
    • packument
    • spec: display versions matching SemVer version or range (edit: or tag)
    • json: output JSON
    • fields: fields that should be listed
  • PackageField (no changes)
  • PackageValue (no changes)

(Lars Willighagen) #18

Third try. With the newfound lack of lack of columns, I think I have addressed all the issues with the first one, so here’s a PR:

(Lars Willighagen) #19

I just saw that there’s an Ink 2 (beta) with flexbox support, which… makes a lot of stuff easier, I think. There are a lot of hacks going on in my code right now to make newlines work. Time for a refactor!

(Kat Marchán) #20

oh cool! I’m cool refactoring to use tink2 btw! /cc @chrisforrette