blacksmith

by Indatus

Indatus / blacksmith

Blacksmith is a code generation tool which automates the creation of common files that you'd typical...

198 Stars 15 Forks Last release: Not found MIT License 78 Commits 8 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:

Blacksmith

Blacksmith is a code generation tool which automates the creation of common files that you'd typically create for each entity in your application.

Blacksmith works nicely with the Laravel PHP framework but does not actually depend on Laravel or extend an Artisan task, it is stand alone. This allows you to use it for code generation from a template anywhere on your filesystem. In fact, while some of the generator specific template variables and post-generation tasks of the Intelligent Laravel Generators are Laravel specific; if the code you want to generate uses studly case and snake case naming, you could generate any code you wanted: Java, JavaScript etc.


Build Status Code Coverage Scrutinizer Code Quality

Out of the box for the 1.0.0 release Blacksmith ships with a Laravel hexagonal architecture configuration and templates. Why? Because this is what I needed first.

Note: If you want to get started with the hexagonal architecture referenced above for a new app. Use Foreman with this example config (changing the 'from' paths appropriatley).

If you don't like the templates + configuration shipped with Blacksmith, don't worry you can make your own custom templates tell Blacksmith how to load them with a JSON config file. Then you just pass that config file's path as an optional argument to Blacksmith's

generate
command and presto, your custom templates and config are used.

Attribution: Blacksmith was inspired by, and even borrows some code from Jeffrey Way's fantastic MIT licensed Laravel-4-Generators package

README Contents

What does it do

Out of the box Blacksmith ships with the following generators:

Single Generators (generates one file)

  • model
  • controller
  • seed
  • migration_create
  • view_create
  • view_update
  • view_show
  • view_index
  • form
  • test_unit
  • test_functional
  • service_creator
  • service_updater
  • service_destroyer
  • validator

Aggregate Generators (calls 1 or more other generators) *

scaffold
- calls all generators above with the given arguments

Installation

Download the PHAR

The simplest method of installation is to simply download the blacksmith.phar file from this repository.

(Optional) Move and set permissions Now if you'd like you can move the PHAR to

/usr/local/bin
and rename it to
blacksmith
for easy access. You may need to grant the file execution privileges (
chmod +x
) before running commands.

Compile from source

To compile the blacksmith.phar file yourself, clone this repository and run the

box build
command. To run box commands, you must install kherge/Box.

See optional move and permissions above.

Updating Blacksmith

To update Blacksmith, you may use the

blacksmith self-update
command.

Usage

Blacksmith generation commands have the following signature:

blacksmith generate {entity} {generator} [config_file] --fields="field1:type, field2:type"

In the example above the

config_file
argument and
--fields
option are both optional. {entity} is the name of the entity in your use case that you are generating code for, and {generator} is the generator you want to run.

To declare fields, use a comma-separated list of key:value:option sets, where key is the name of the field, value is the column type, and option is a way to specify indexes or other things like unique or nullable. Here are some examples:

  • --fields="first:string, last:string"
  • --fields="age:integer, yob:date"
  • --fields="username:string:unique, age:integer:nullable"
  • --fields="name:string:default('John'), email:string:unique:nullable"
  • --fields="username:string[30]:unique, age:integer:nullable"

Please make note of the last example, where we specify a character limit:

string[30]
. This will produce
$table->string('username', 30)->unique();

An example without placeholders might look like this:

blacksmith generate User scaffold ~/blksmth/cfg.json --fields="username:string:unique, age:integer:nullable"

Note: Blacksmith works from your current working directory, so if you have a template that gets written to a releative path, that will be relative to your current directory when you run Blacksmith. For Laravel this directory should be the application root.

Getting Started

While Blacksmith comes packaged with templates and base configuration file, it's likely you'll want to download the templates and customize them to suit your needs. This will also require you create your own config file which you can read more about in the Config File section.

As you begin to generate you may notice some interfaces and classes referenced in templates that were not generated. This is not a mistake. Any classes you only create one time are not generated by Blacksmith and can be obtained from Blacksmith-contracts.

The Config File

The Blacksmith config file is written in JSON and has a specific format. Blacksmith will validate the file's format before use and provide errors if there is a mis-configuration.

The config file has a root level item for each single generator, and a root level item for config_type. The config_type element leaves the door open for subsequent configurations like "mvc" that would require a different collection of generator keys to be present.

Here is a partial view of the template, for a full template checkout the default here:

{
    "config_type": "hexagonal",

"model": {
    "template": "model.txt",
    "directory": "app/models",
    "filename": "{{Entity}}.php"
},
"controller": {
    "template": "controller.txt",
    "directory": "app/controllers",
    "filename": "{{Entities}}Controller.php"
},
"migration_create": {
    "template": "migration_create.txt",
    "directory": "app/database/migrations",
    "filename": "{{migration_timestamp}}_create_{{collection}}_table.php"
},
"view_show": {
    "template": "view_show.txt",
    "directory": "app/views/{{collection}}",
    "filename": "show.blade.php"
},

}

The key take away here is that for each singular generator there are sub elements for template, directory, and filename.

  • template - the template file to use for this generator relative to the config file
  • directory - the directory where the final parsed template should be written, relative to the directory you were in when Blacksmith was executed.
  • filename - the filename the parsed template should be saved as

Note: if the destination directories do not exist Blacksmith will create them.

To skip a generator, set it's configuration to

false
. This can be useful to skip generating views when you're building an API.
    "migration_create": false,

You can also see in the partial config file example that you can use template variables provided by the generator in both the directory and filename values of the configuration.

Templates

Blacksmith templates use Mustache syntax, otherwise they are just plain text files. See below for the available variables that can be used.

The variables made available for each generator can be used in the generator template file or within the JSON config file in the directory, and filename values.

Template Variables

Standard Variables

Each Blacksmith generator will always have the following standard variables available for use in the generator template or in the config's directory, and filename values.

Variable

Description Output Example

Entity
| Singular studly cased entity name | Order
Entities
| Plural studly cased entity name | Orders
Base
| Studly cased directory path | Order/Sub/Directory
Namespace
| Studly cased namespace | Order\Sub\Directory
collection
| Plural underscore cased entity name | orders
instance
| Singular underscore cased entity name | order
fields
| Associative multi-dimensional array of field names and attributes |
['name' => ['type' => 'string']]
year
| The current year | 2014

Generator Specific Variables

Generator specific variables may only be available in certain generators because the use is specific:

Variable

Description Generators Output Example

headings
| Array of field names that can be used as table headings | viewindex
view
show |
['name', 'age']
cells
| Array of code snippets that can be used to ouptut values in table cells | viewindex
view
show |
["\$user->name", "\$user->age"]
mock_attributes
| Array of fields set with mock data | functionaltest |
["'name' => 'dreamcatcher',",]
columns
| Array of schema builder column creation code snippets | migration
create |
["\$table->string('name');"]
migration_timestamp
| Timestamp used for migration filenames | migrationcreate | 20140313042956
form_rows
| Array of element + label Laravel form builder code for the passed in fields | form | see below

form_rows
Output Example:
[
    [
        'label' => "{{ Form::label('name', 'Name:') }}",
        'element' => "{{ Form::text('name') }}"
    ]
]

Note: with the exception of

migration_timestamp
all the generator specific variables are arrays. The content and count will vary as it is based on the
--fields
that were passed in.

Intelligent Laravel Generators

Outside of template variables some of the generators have laravel specific actions that are taken after the template is generated and written out IF conditions are right. The table below describes each use case:

Generator

Extra Functionality

migration_create
| Tests to see if
app/database/seeds/DatabaseSeeder.php
exists relative to the current directory. If so it checks that the newly generated seeder isn't already present in
DatabaseSeeder.php
. If the file exists, and entry is not present it will be added.
scaffold
| Tests to see if
app/routes.php
exists relative to the current directory. If so the routes file will be appended with a
Route::resource()
entry for the newly created resourceful controller.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.