0 Newt model command provides an interactive way for generating and managing your data models expressed in the Newt YAML file. It let's you avoid directly typing YAML. While it is interactive it is still a command you run in your shell. It lets you adding, modify and remove models. When modify a model it lets you add, modify and remove elements. When you are done machine changes at the application, model or element level you can "quit" to indicate your are done making changes. When you quit at the models list level it will prompt you to save the changes if you've made any.
Since your Newt application flows from your data model(s) the modeler takes care of creating the routes and templates entries for each model you add. Likewise takes care of cleaning up any routing or template references previously generated the modeler when you remove a model.
By using newt config, newt model and newt generate you can create a a deliverable Newt application. The minimal application will depend on Postgres+PostgREST as well as Mustache templates for rendering the human user interface.
In this short tutorial we are going to create a web application that says describes the contents of a garden. We will use the newt command to configure, model and generate our application.
We will cover three steps. Creating a new "garden.yaml" file with "config" action, modeling our garden data and generating some code.
We can create or update our "garden.yaml" using our standard newt config command. For this tutorial just accept the defaults.
newt config garden.yamlThe first stage of the modeler is to present a list of existing models. It then gives you options of "add", "remove" "modify", "config", and "quit". Launch our modeler with newt model garden.yaml
newt model garden.yamlBy default the command newt config manages the "applications" attribute in our "garden.yaml" file. It doesn't create any models, routes, or templates.
created an "garden" model. When we use newt model the models defined will then trigger the creation of routes and templates attributes needed by the application.
When you launch net model you are presented with a text menu that looks like this.
Enter menu letter and id
Menu [a]dd, [m]odify, [r]emove, [q]uit (making changes)No models have been defined yet. Let's add one called "garden" by press "a" key followed by enter key.
You should now see a prompt like below.
Enter model id to add:Type in "garden" without the quotes, then press enter key
Now the menu should look like this.
Enter menu letter and id
1: garden
Menu [a]dd, [m]odify, [r]emove, [q]uit (making changes)An empty model called "garden" has been created. If we want to remove it we would type the following ending in pressing the enter key.
remove gardenAt this point the menu would not show any models. Add "garden" back so we can continue with modifying our newly created "garden" model.
This is what you can type as a short cut.
add gardenYou should see this menu again.
Enter menu letter and id
1: garden
Menu [a]dd, [m]odify, [r]emove, [q]uit (making changes)We now ready to "modify" our model. You'll see the theme of Menu [a]dd, [m]odify, [r]emove, [q]uit (making changes) through out the modeling process targeting the specific level you're refining.
Type the following at this menu.
modify gardenThis will take you to a new menu focused on managing the garden model.
Enter menu letter to manage model
1: Model Id: garden
2: Descriptions: ... description of "garden" goes here ...
3: Elements: identifier
Menu: model [d]escription, [e]lements, [q]uit (making changes)This menu is slightly different because we have different types of parameters that can be modify in our model. An individual model contains an identifier. This you can't change but is displayed so you know what you are modifying. At the "Menu": line we see that we have choices of description, element and quit. Let's modify the description first to be something less generatic.
Type the following followed by pressing the enter key.
d This is a model of my gardenNotice that I typed "d" instead of the whole word "description". This short cut can be used through the modeler where
a single letter is indicated by square brackets, [d]escription would mean you could type "d", [q]uit would mean
you can type "q" instead of "quit".
The updated menu should look like this.
Enter menu letter to manage model
1: Model Id: garden
2: Descriptions: This is a model of my garden
3: Elements: identifier
Menu: model [d]escription, [e]lements, [q]uit (making changes)When a model is added one element is created as an example. That element is called "identifier" which stands for object identifier. To manage objects we a specific unique key to access them. That is what an object identifier provides. At the SQL level this is analogous to a primary key.
Elements are the specific data held and managed by your model. You can think of them as the columns in a spreadsheet. We many have lots of objects just as you can have lots of rows in a spreadsheet.
Let's modify our element list. The first thing we'll do is get rid of "identifier" and create a new primary key called "garden_id".
Type the letter "e" and press enter.
You should see this new menu.
Enter menu letter and id
1: identifier
Menu [a]dd, [m]odify, [r]emove, [q]uit (making changes)This is a list of our model's elements. We can remove the "identifier" by typing the following followed by pressing the enter key.
r identifierThe list should now look like
Enter menu letter and id
Menu [a]dd, [m]odify, [r]emove, [q]uit (making changes)Now let's add our "garden_id" by typing the following and then pressing the enter key
a garden_idThe menu now should look like
Enter menu letter and id
1: garden_id
Menu [a]dd, [m]odify, [r]emove, [q]uit (making changes)We are ready to modify our garden_id and make it the primary key. Type the following and press the entery key.
m garden_id
This takes us to the element menu.
Select menu item to model properties
1: id garden_id
2: type input
3: pattern
4: attributes name
title
5: primary key false
Menu [t]ype, [p]attern, [a]ttributes, [o]bject id flag, [q]uit (making changes)
Like the model menu we have options to modify the common properties, e.g. type, pattern, and importantly primary key via [o]object id flag.
Enter the letter "o" and press enter. Notice how number five changes. The menu should now look like
Select menu item to model properties
1: id garden_id
2: type input
3: pattern
4: attributes name
title
5: is object id true
Menu [t]ype, [p]attern, [a]ttributes, [o]bject id flag, [q]uit (making changes)Because is object id can be either true (on) or false (off) you are not prompted to set its value. Now let's take a look at attributes. You see "name" and "title". Name is used when this element's HTML is rendered. The name attribute is set by the contents of name. Similarly the title attribute (used for hover text in a form element) is all set. Managing an element's attributes is done by pressing "a" and then the enter key. You you've done that you should see the following.
Enter menu letter and id
1: name
2: title
Menu [a]dd, [m]odify, [r]emove, [q]uit (making changes)Let's change the title text to explain what garden_id is.
Type the following followed by pressing the enter key.
m titleThe menu should now show this.
Enter title's value:Enter a description of the garden_id as follows finishing by presssing the enter key.
This is the unique identifier for the garden model.Now that we're done changing the attributes press "q" and then the enter key. This will take us back "up" the element level menu.
Select menu item to model properties
1: id garden_id
2: type input
3: pattern
4: attributes name
title
5: is object id true
Menu [t]ype, [p]attern, [a]ttributes, [o]bject id flag, [q]uit (making changes)Typing "q" and enter again will take us up further to the list of elements in our model.
Enter menu letter and id
1: garden_id
Menu [a]dd, [m]odify, [r]emove, [q]uit (making changes)Typing "q" and enter again will show us a summary of our model.
Enter menu letter to manage model
1: Model Id: garden
2: Descriptions: This is a model of my garden
3: Elements: garden_id
Menu: model [d]escription, [e]lements, [q]uit (making changes)Typing "q" and pressing enter here will take us to our list of models.
Enter menu letter and id
1: garden
Menu [a]dd, [m]odify, [r]emove, [q]uit (making changes)Typing "q" and pressing enter one last time you should now be prompted to save your model.
Save before exiting (Y/n)?Answer "y" and press enter.
This will save the Newt YAML file and bring us back to the shell prompt. If you use the more command you can see the YAML we've created.
more garden.yamlThis should return something like this.
#/usr/bin/env newt check
#
# This was generated by rsdoiel on 2024-05-09 with newt version 0.0.8 8453132.
#
applications:
router:
port: 8010
template_engine:
port: 8011
base_dir: views
partials_dir: partials
ext_name: .hbs
postgres:
port: 5432
dsn: postgres://{PGUSER}:{PGPASSWORD}@localhost:5432/garden.yaml
postgrest:
app_path: postgrest
conf_path: postgrest.conf
port: 3000
enviroment:
- PGUSER
- PGPASSWORD
models:
- id: garden
description: This is a model of my garden
elements:
- type: text
id: garden_id
primary_key: true
attributes:
name: garden_id
title: This is the unique identifier for the garden model.
required: true
- type: text
id: description
attrbiutes:
name: description
title: This holds a description of hte garden element
required: true
routes:
- id: garden_create
request: GET /garden_create
description: Handle retrieving the webform for garden create
pipeline:
- service: POST http://localhost:8011/garden_create
description: Display a garden for create
- id: garden_create
request: POST /garden_create
description: Handle form submission for garden create
pipeline:
- service: POST http://localhost:3000/rpc/garden_create
description: Access PostgREST API for garden create
- service: POST http://localhost:8011/garden_create_response
description: This is an result template for garden create
- id: garden_update
request: GET /garden_update/{garden_id}
description: Handle retrieving the webform for garden update
pipeline:
- service: GET http://localhost:3000/rpc/garden_read/{garden_id}
description: Retrieve garden from PostgREST API before update
- service: POST http://localhost:8011/garden_update
description: Display a garden for update
- id: garden_update
request: POST /garden_update
description: Handle form submission for garden update
pipeline:
- service: PUT http://localhost:3000/rpc/garden_update/{garden_id}
description: Access PostgREST API for garden update
- service: POST http://localhost:8011/garden_update_response
description: This is an result template for garden update
- id: garden_delete
request: GET /garden_delete/{garden_id}
description: Handle retrieving the webform for garden delete
pipeline:
- service: GET http://localhost:3000/rpc/garden_read/{garden_id}
description: Retrieve garden from PostgREST API before delete
- service: POST http://localhost:8011/garden_delete
description: Display a garden for delete
- id: garden_delete
request: POST /garden_delete
description: Handle form submission for garden delete
pipeline:
- service: DELETE http://localhost:3000/rpc/garden_delete/{garden_id}
description: Access PostgREST API for garden delete
- service: POST http://localhost:8011/garden_delete_response
description: This is an result template for garden delete
- id: garden_read
request: POST /garden_read
description: Retrieve object(s) for garden read
pipeline:
- service: GET http://localhost:3000/rpc/garden_read/{garden_id}
description: Access PostgREST API for garden read
- service: POST http://localhost:8011/garden_read
description: This template handles garden read
- id: garden_list
request: POST /garden_list
description: Retrieve object(s) for garden list
pipeline:
- service: GET http://localhost:3000/rpc/garden_list
description: Access PostgREST API for garden list
- service: POST http://localhost:8011/garden_list
description: This template handles garden list
description: Retrieve object(s) for garden read
pipeline:
- service: GET http://localhost:3000/rpc/garden_read/{garden_id}
description: Access PostgREST API for garden read
- service: POST http://localhost:8011/garden_read
description: This template handles garden read
- id: garden_list
request: POST /garden_list
description: Retrieve object(s) for garden list
pipeline:
- service: GET http://localhost:3000/rpc/garden_list
description: Access PostgREST API for garden list
- service: POST http://localhost:8011/garden_list
description: This template handles garden list
templates:
- id: garden_create
request: /garden_create
template: garden_create_form
description: Display a garden for create
- id: garden_create
request: /garden_create_response
template: garden_create_response
description: This is an result template for garden create
- id: garden_update
request: /garden_update
template: garden_update_form
description: Display a garden for update
- id: garden_update
request: /garden_update_response
template: garden_update_response
description: This is an result template for garden update
- id: garden_delete
request: /garden_delete
template: garden_delete_form
description: Display a garden for delete
- id: garden_delete
request: /garden_delete_response
template: garden_delete_response
description: This is an result template for garden delete
- id: garden_read
request: /garden_read
template: garden_read
description: This template handles garden read
- id: garden_list
request: /garden_list
template: garden_list
description: This template handles garden listWhile the application would not be useful yet, our garden model only contains an id, we could generate our application's SQL, PostgREST configuration and Mustache templates
with newt generate garden.yaml.
As an exercise I recommend adding additionals elements to our garden model such as plant, location and then regenerate the code an notice what changes in the setup.sql and model.sql as well as in our mustache templates.
This last step is one short command but it will generate many files. Type the following command at the shell prompt.
newt generate garden.yamlThis will generate the following files.
postgrest.conf
setup.sql
models.sql
validator.ts
views/garden_create_form.hbs
views/garden_create_response.hbs
views/garden_delete_response.hbs
views/garden_read.hbs
views/garden_update_response.hbs