litestar icon indicating copy to clipboard operation
litestar copied to clipboard

Enhancement: Add a CLI

Open Goldziher opened this issue 3 years ago • 16 comments

We should consider adding a CLI that will allow users to quickly scaffold a project with a default folder / file structure, readme, tooling etc.

A good example is the NestJS CLI.

I'd like to discuss this proposal in this issue.

Goldziher avatar Jun 17 '22 10:06 Goldziher

poetry new is the first example that stands out to me. They have cleo.

peterschutt avatar Jun 17 '22 11:06 peterschutt

We should consider adding a CLI that will allow users to quickly scaffold a project with a default folder / file structure, readme, tooling etc.

I think it is a great idea in context of Starlite project.

A good example is the NestJS CLI.

I really like the one that Vue 3 has: https://vuejs.org/guide/quick-start.html#local. Very powerful yet approachable.

vrslev avatar Jun 17 '22 18:06 vrslev

Ok. So, let's talk about structure-

Given that you probably want to install a CLI as as a global executable outside your project, I think it might be a good idea to separate it out into its own package and publish it separately. I know sometimes the CLi is a part of the app, but I think here it's going to be an issue - the CLI should be independent from the starlite version IMO.

We should consider whether we want to split it to a different repo, or simply a folder in this repo.

Pros of different repo:

  1. Separation of concerns
  2. No shared dev dependencies
  3. Simpler release process
  4. No need for a monorepo or similar construct

Cons:

  1. A separate code base might make it harder to contribute, e.g. issues etc.
  2. Stars are spread across repos.
  3. No code sharing is possible (no biggy on this case)

Goldziher avatar Jun 18 '22 15:06 Goldziher

Is there anything similar to npm init in Python world? Maybe just cookiecutter?

vrslev avatar Jun 18 '22 19:06 vrslev

What about using cookiecutter together with clap? So you could create a separate repo for the template but still integrate the cli into the "main" repo while using cookiecutter as a base.

JeromeK13 avatar Jul 04 '22 13:07 JeromeK13

I'm open to this idea. I have no experience working with these tools tbh.

Goldziher avatar Jul 04 '22 13:07 Goldziher

Alright I could do a proposal. In general do you care about dependencies in this project? For example is it a problem for using click instead of the default arg-parser?

JeromeK13 avatar Jul 04 '22 13:07 JeromeK13

Would it also mean cookiecutter was a dependency of the standard install?

peterschutt avatar Jul 04 '22 13:07 peterschutt

It will be an extra dependency I assume, so it shouldnt be a problem.

Goldziher avatar Jul 04 '22 13:07 Goldziher

Yes if we would integrate that here. As Goldziher said, I also dont see any problem from my side. But let me propose something and then we can have a further look into how to integrate it

JeromeK13 avatar Jul 04 '22 13:07 JeromeK13

Go for it man, I look forward to seeing your proposal. Thanks for getting involved!

peterschutt avatar Jul 04 '22 14:07 peterschutt

What would be a good project-structure? I think something like this:

src                           # project root  
├── admin-cli.py
├── main.py         
├── /config           # project configuration 
│      ├── base.py   # project settings   
│      ├── local.py   # local settings 
│      ├── prod.py   # production settings 
├── /my_app     
│      ├── controller.py
│      ├── model.py
│      ├── /tests

Easiest would be to include the folderstructure as some template, or have it in a zip. The files itself could contain {{variables}} , which can be replaced using jinja2.

Alex-CodeLab avatar Sep 04 '22 17:09 Alex-CodeLab

What would be a good project-structure? I think something like this:

src                           # project root  
├── admin-cli.py
├── main.py         
├── /config           # project configuration 
│      ├── base.py   # project settings   
│      ├── local.py   # local settings 
│      ├── prod.py   # production settings 
├── /my_app     
│      ├── controller.py
│      ├── model.py
│      ├── /tests

Easiest would be to include the folderstructure as some template, or have it in a zip. The files itself could contain {{variables}} , which can be replaced using jinja2.

cookie-cutter is a good option for generation.

As for the structure - I think @cofin and @peterschutt have some opinions there.

Goldziher avatar Sep 04 '22 18:09 Goldziher

cookie-cutter is a good option for generation.

cookie-cutter is nice, but then it can only do one thing: build a project-structure. Cookie-cutter does more or less the same: take a template folderstructure, and search/replace with Jinja, and copy it to some destination.

When I read cli, I think of a command-line application that could be extended with new commands as well. For example, in Django there are about 20 commands (startproject, startapp, clear_cache, create_superuser,... ), and each module can easily add new ones. (Such a cli could even call cookiecutter in the background if you really want to use that )

Alex-CodeLab avatar Sep 05 '22 08:09 Alex-CodeLab

Cookiecutter can also run pre and post-generation callbacks but it would probably be best to call cookiecutter instead of having it do the calling

john-ingles avatar Sep 06 '22 17:09 john-ingles

I dont have a strong opinion one way or the other - whatever works best.

Goldziher avatar Sep 06 '22 18:09 Goldziher

Assigning this to myself

Goldziher avatar Oct 01 '22 09:10 Goldziher

Ok, so for the CLI we need to flush out some requirements before we proceed. I will be closing this issue and create a discussion instead.

Goldziher avatar Oct 15 '22 20:10 Goldziher

Reopening this because of popular demand

provinzkraut avatar Dec 14 '22 11:12 provinzkraut

Todo

  • [x] Basic CLI framework
  • [x] CLI commands
    • [x] Running an application
    • [x] Application autodiscovery
    • [x] Routing table overview
  • [x] Utils to register commands dynamically

provinzkraut avatar Dec 22 '22 09:12 provinzkraut

After experimenting with the CLI, and trying it out as a separate package I've come to the conclusion that it's not necessary or desirable for the following reasons:

Publishing it as a standalone package means that it should not have a hard dependency on Starlite. This also means that every code that interacts with Starlite needs to be imported within the commands that use it, leading to quite a bit of messy code. You can see this here

This decoupling also means that there's effectively only one command that's going to be usable when invoked outside of an already existing Starlite project: The command to create a new Starlite project.

Since there is only one command that doesn't depend on a Starlite installation (i.e. doesn't interact with an application instance) I think moving forward it makes most sense to publish a separate utility for this command. It really is its own thing and has, neither conceptually, code or usage wise, anything to do with the rest of the CLI. I propose we create a create-starlite-app package, that can simply be run e.g. with pipx run create-starlite-app and include the CLI parts that interact with an existing application with the regular starlite package.

This approach also means less dependencies required for each package (the only dependency they'd have in common would be click), which is always a nice thing and we could potentially include the CLI by default instead of an extra.

provinzkraut avatar Dec 22 '22 09:12 provinzkraut