CLI: Sensible Defaults, Error Handling and Delete Macros for Generators
nsipplswezey opened this issue · comments
It's easy, and common when starting, to make mistakes with the CLI generators.
So much else in Nodal is easy, straightforward and delivers far above expectations, that relatively speaking a couple CLI errors and needing to memorize specific syntax of CLI are probably one of the greatest barriers to entry. I think this is a striking complement as well as a great area for low-hanging-fruit productivity improvement in Nodal.
Here are a couple examples from experience introducing friends to Nodal, followed by proposals for defaults, error handling and delete/undo
Not specifying a model for a controller
Example:
nodal g:controller v1
without a --for
flag generates an empty controller that implements methods that map directly to request type GET
POST
PUT
DEL
, which implement this.render()
which returns an undefined
response.
Sensible Default:
I think the direct method mapping makes sense.
Replace this.render()
with this.respond({ message: METHOD + " to " + ENDPOINT + " handled by " + CONTROLLER })
Forgetting to namespace a controller
Example:
nodal g:controller --for tweet
Will generate a controller outside of the namespaced directory, with an non-namespaced endpoint.
This is irritating and common if it's the first time you've thought about namespacing.
Error Handling:
If a namespaced controller exists, prompt the user with "you already have a namespace v1. Would you like to namespace this controller to v1 as well? y or N"
Undo:
nodal g:undo
Undo's whatever last generator command was run in this session.
So if I run a nodal g:controller --for tweet
and I don't name space it, and I test my end point and realize 'shit! I meant to name space that.
I my process is:
$ nodal g:controller --for Tweet
$ nodal g:undo
$ nodal g:controller v1 --for Tweet
Or if I do:
$ nodal g:controller v1
$ nodal g:undo
$ nodal g:controller v1 --for Tweet
Or alternatively delete
Might look something like
$ nodal g:controller v1
$ nodal delete v1
$ nodal g:controller v1 --for Tweet
I think honestly the interface should be either undo
or delete
; not both.
g:delete target
is dissonant to me.
Personally I think the undo metaphor is much better, as it fits within the scope of the g:
imperative, and my mental model of how I would like a generator to work.
The domain space of genertor's are focused, and pretain to the specific scope of "solve this problem for me." An undo allows me to say "whoops! My bad! I wen't solve THIS problem."
Additionally, nodal generators are typically sequential.
$ nodal g:model Tweet user_id:int body:string
$ nodal g:controller v1 --for Tweets
$ nodal db:migrate
is the first Nodal CLI pattern that any new user learns. So the undo metaphor makes a lot of sense, because I'm just going on step back in my process. Or two if need be. Or three. And then running each of those steps over again.
One challenge with undo is either: reimplement generators using an abstraction that makes them inherently reversible; perhaps using an interface built over an immutable history data structure that exists in the project.
Or implementing something quicker and simpler, but limiting the scope of undo to say the last 3 generator commands. I don't prefer this solution.
Incomplete generator commands
Example
nodal g:controller v1 --for
Error Handling
Just throws a Cannot read property 'length' of undefined
It could give an error message like Error: No model specified after --for flag. It looks like you wanted to build a controller for a specific model, but didn't specify the model.
Namespacing a controller without specifying a model with the --for flag
nodal g:controller v1 testController
Might be expected to generate a default controller named testController
and place the controller in the v1
directory.
Instead it throws a somewhat cryptic error:
return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
^
Error: ENOENT: no such file or directory, open './app/controllers/v1_controller.js'
Default Behavior
Just generate a default controller in the name spaced directory.
Messing up my model schema
nodal g:model Tweet userId:int body:string
Oh shit. I meant user_id:int body:string
Instead of going into my migration and changing this directly, I'd like to just do a
nodal g:model Tweet userId:int body:string
nodal g:undo
nodal g:model Tweet user_id:int body:string
Forgetting to migrate after generating a new model
This is a common error if Nodal is the first time you're using the migrations abstraction to progressively manage your models and database layer.
The nodal server will crash every time a new model is generated, because a migration is necessary to make the model work.
I don't mind this for two reasons.
First, the error message highlights how readable Nodal error messages are.
Second, it highlights the specific line of code that links our backing schema and tables to our model instances.
Third, models and migrations are seperate concerns. So lumping model creation and db migration might be one fewer command, but comes at the expense of blurring the separation of concerns, which is more valuable.
An empty nodal
command generates a Cannot read property 'split' of undefined.
This could be handled better,