File | Date | Author | Commit |
---|---|---|---|
bin | 2015-04-02 |
![]() |
[ce1ef8] - make bin/crystal executable |
lib | 2015-04-02 |
![]() |
[2a9818] - fixed search |
src | 2015-04-02 |
![]() |
[691955] - fixed search bug |
test | 2015-04-02 |
![]() |
[5bed5e] init |
.gitignore | 2015-04-02 |
![]() |
[5bed5e] init |
AUTHORS | 2015-04-02 |
![]() |
[783952] - updated project name |
LICENSE | 2015-04-02 |
![]() |
[5bed5e] init |
README.md | 2015-04-02 |
![]() |
[ec15b6] - updated version to 0.2.1 |
crystal.yml | 2015-04-02 |
![]() |
[ec15b6] - updated version to 0.2.1 |
package.json | 2015-04-02 |
![]() |
[ec15b6] - updated version to 0.2.1 |
Crystal: Node.JS Edition
crystal
is an open-source platform for automated code generation, versioning, licensing, security and deployment of popular languages and frameworks.
Artificial intelligence was created the moment the first line of code was written. Now it's written in C#, PHP & JavaScript.
Our goal is to perfect code: to embrace the creativity and unique ideas of various languages, frameworks and scripts, and make it as efficient, re-usable and intelligent as possible.
crystal
is written in node.js
and distributed by npm
:
After downloading and installing node.js
and npm
, run:
npm install crystal -g
The option -g
installs crystal
globally so you can run crystal
from any directory.
Once installed, crystal
runs as a CLI program.
Note: be sure to install crystal
with the -g
option to ensure it is installed globally and can be used for any directory.
crystal
accepts the commands and arguments below.
Required arguments are surrounded by tags <>
and optional arguments are surrounded by brackets []
.
If a command accepts the dir
argument and no dir
is specified, it uses the current working directory.
Note: Commands that use the dir
argument are looking for a Crystal Config File. If one doesn't exist, the command will return an error!
# build project from current or specified directory
crystal build [dir]
# read/write value from/to cache
crystal cache key [value]
# clean project from current or specified directory
crystal clean [dir]
# load data
crystal data [fixture]
# get or set default value
crystal default [key] [value]
# get help
crystal help
# initialize a crystal project
crystal init [dir]
# install a generator
crystal install <generator>
# publish project from current or specified directory
crystal publish [dir]
# run project from current or specified directory
crystal run [dir]
# search for public generators
crystal search <generator>
# signup for crystal
crystal signup
# test project
crystal test
# update generators
crystal update
# get crystal version
crystal version <major|minor|patch>
There are many ways to use crystal
but the two most common scenarios are:
crystal
for your projectscrystal
to create generatorscrystal
is powerful. It has several generators to choose from and helps you bootstrap your projects in no time.
But it doesn't stop there. crystal
is meant to be used for projects on an ongoing basis. It helps you deliver high quality code for every story, every sprint and every epic. It's there for launch, maintenance and upgrades.
If you are happy using crystal
to make robust apps (or save the world), then use it for your projects and enjoy the generators made by the wonderful community of crystal
.
If you haven't found the right one. Or if you could do it better. Or just want to give a whirl:
Try creating a generator for you favorite language, framework or even your own custom code.
Generators are projects that are meant to be used as generators. In other words, a project is a project unless it:
gen
key in the Crystal Config Filegen
folder in the Crystal Source Directory (default: ./src
)Once this has been done, the crystal
project can then be used a generator for other projects. Or generators. Or itself.
If you want to share it with the world, then you'll also need to:
/src/test
)crystal publish
Below are all of the folders that can be used by crystal
.
Note: The only required file is a Crystal Config File (default: crystal.yml
).
lib/
- output directory (where generators push to)src/
- source directory (where generators pulls from)code/
- code filesdoc/
- documentation files$chapter_name
- name of a chapter$page_name
- name of a pagegen/
- gen files used for generators$gen_file.hbs
a generator filespec/
- spec files that describe the projectmodel/
$model_name.yml
- name of a modelcrystal.yml
- crystal config fileIn order for your project to properly integrate with crystal
, a config file must be added to a directory in your project (preferably in the project's root directory).
It can be created in the following formats:
Discovery of this file happens in the following order:
crystal.yml
crystal.yaml
crystal.cson
crystal.json
crystal.xml
For example, if you had both a crystal.yml
file and crystal.cson
file, only the crystal.yml
would be loaded.
The only required fields in the crystal config file are name:
and version:
. Everything else is optional.
Adding crystal
to a new project is easy.
Adding crystal
to an existing project is as easy as adding it to a new project.
The options below can be used for the Crystal Config File:
# the project's name (required)
name:
# the project's version, must be semver 2.0 compliant (required)
version:
# the project's description (required)
description:
# true or false
private:
# the chief author's name, email & url
author:
name:
email:
url:
# the project's copyright (example: 2015 Acme, Inc.)
copyright:
# the project's documentation
doc:
$chapter-name:
title: # the chapter's title
pages:
$page-name:
title: # the page's title
# the project's repository
repository:
type: # git or svn
url:
# the project's generator
gen:
file:
$file: # name of the file (without the extension)
dest: # the destination of the file, use '.' for root (default: lib)
mapping:
model:
details:
name:
format:
case: '<camel|lower|proper|upper>' (lowercase)
spacing: '<dash|none|underscore>' (underscore)
type:
bool: <'DETAIL_TYPE'|false>
date: <'DETAIL_TYPE'|false>
decimal: <'DETAIL_TYPE'|false>
image: <'DETAIL_TYPE'|false>
model: <'DETAIL_TYPE'|false>
number: <'DETAIL_TYPE'|false>
string: <'DETAIL_TYPE'|false>
time: <'DETAIL_TYPE'|false>
name:
format:
case: '<camel|lower|proper|upper>'
spacing: '<dash|none|underscore>'
spec: # custom spec
$field_name: # add custom field with unique name
required: <true|false>
type: '<option|string>'
# the generators used by the project (yes, generators can use other generators)
generators:
$generator_name: # add generator by name
pass: set to `true` to skip this generator when used by another generator (pass to projects that use this generator instead)
path: # the path used for the generator's output (the default is 'lib')
spec: # spec variables to pass to the generator
version: # the version of the generator to be used
# languages based on generator's output
languages: # optional
- <csharp|go|java|js|nodejs|php|python|ruby|other>
# scripts ran for specific commands
scripts:
build:
- $cmd # example - npm update
run:
- $cmd
test:
- $cmd
The Directory Structure for the spec is like:
# usage
- model/
- $model_name.$model_format
# example
- model/
- order.yml
- product.yml
- user.yml
Each file has the following options:
Config Variables are defined in the Crystal Config File and can be used at any level within the document.
{{@name}} string
{{@version}} string
{{@description}} string
{{@private}} bool
{{@author}} object
{{@author.name}} string
{{@author.email}} string
{{@author.url}} string
{{@copyright}} string
{{@repository}} object
{{@repository.type}} string
{{@repository.url}} string
# model
{{model}}
{{$model_name}} object
Generators generate code.
Some are big and produce entire libraries for Restful APIs, models and other robust services. Others are small and only produce a single file such as a README.md, AUTHORS or .gitignore file.
They can work together or alone. They can have one purpose or many. They can be public or private. And they can be created from scratch or added to an existing project.
Generators are what make crystal
useful to you and others. So use them. Make them. Make a lot of them. Then make generators for your generators and generators for your generators' generators.
Loading generators is easy and can happen in a few ways.
Usually generators are added to your project's crystal config such as this readme generator:
# crystal config
generators:
readme:
version: latest
Then update your crystal project:
# example
cd $PROJECT_PATH
crystal update
This is the quick way to add a generator to your project and use it.
If you'd like to load a generator manually, you can do so by running:
# usage
crystal install <generator>
# example
crystal install readme
This will install the generator to your crystal home directory (set as ~/.crystal
by default).
This is useful for checking out the source code for a generator before using it.
Creating Generators puts you in control of code generation.
Generators use Handlebars syntax and are processed through a series of code templates & configurations to produce source code.
Whether you wish to create a completely unique generator or fine-tune an existing generator, creating generators allows you full control of the code that is produced.
Below is an example crystal.cson
file for the Django framework which defines python
as a language, model
as a pattern and the mapping for various types of details.
Since this example does not include the iterator
option, each model is compiled into a single file named models.py
.
languages:
- python
gen:
file:
dest: models.py
models:
mapping:
model:
details:
type:
bool: BooleanField
date: DateField
decimal: DecimalField
image: ImageField
model: ForeignKey
number: IntegerField
string: CharField
time: DateTimeField
Below is an example crystal.cson
file for the Doctrine framework which defines php
as a language, model
as a pattern and does not include mapping of detail types, since Doctrine doesn't use these.
Since Doctrine defines each model in a separate file, the files
object is used to place each file in the model/
directory.
files:
model:
data: models
dest: "models/{{name.pascal}}.php"
languages:
- php
patterns:
- model
gen/
. (GENERATOR files)
crystal.cson
Here are the available options for each project:
{{author}} object
{{email}} string
{{name}} string
{{model}}
{{MODEL_NAME}} object
.. (same options as {{models}})
{{models}} array
{{detail}} object
{{DETAIL_NAME}} object
.. (same options as {{models.details}})
{{details}} array
{{max}} object
{{length}} integer
{{number}} integer
{{min}} object
{{length}} integer
{{number}} integer
{{name}} string
{{required}} boolean
{{type}} string
{{unique}} boolean
{{has}} object
{{DETAIL_NAME}} boolean
{{name}} string
{{project}} object
{{copyright}} string
{{description}} string
{{name}} string
models
Data StructureThe models
Data Structure is useful when iterating models over multiple files.
{{author}} object
{{email}} string
{{name}} string
{{detail}} object
{{DETAIL_NAME}} object
.. (same options as {{models.details}})
{{details}} array
{{max}} object
{{length}} integer
{{number}} integer
{{min}} object
{{length}} integer
{{number}} integer
{{name}} string
{{required}} boolean
{{type}} string
{{unique}} boolean
{{has}} object
{{DETAIL_NAME}} boolean
{{name}} string
{{project}} object
{{copyright}} string
{{description}} string
{{name}} string
The example below illustrates how to use the Generator structure to create a Documentation Generator. This same logic can be applied to any other type of Generator including API Generators, Database Generators, Model Generators and more.
# {{@name}} {{@version}}
by {{@author.name}} <{{@author.email}}>
## Models
{{#each models}}
### {{name}}
#### Properties
<table>
<tr>
<th>Name</th>
<th>Type</th>
<th>Required</th>
<th>Unique</th>
</tr>
{{#each details}}
<tr>
<td>{{name}}</td>
<td>{{type}}</td>
<td>{{#if detail.required}}x{{/if}}</td>
<td>{{#if detail.unique}}x{{/if}}</td>
</tr>
{{/each}}
</table>
{{/each}}
To test this example:
gen
and add a file named README.md
.