A scaffolding library for the modern web.
Schematics are generators that transform an existing filesystem. They can create files, refactor existing files, or move files around.
What distinguishes Schematics from other generators, such as Yeoman or Yarn Create, is that schematics are purely descriptive; no changes are applied to the actual filesystem until everything is ready to be committed. There is no side effect, by design, in Schematics.
|Schematics||A generator that executes descriptive code without side effects on an existing file system.|
|Collection||A list of schematics metadata. Schematics can be referred by name inside a collection.|
|Tool||The code using the Schematics library.|
|Tree||A staging area for changes, containing the original file system, and a list of changes to apply to it.|
|Rule||A function that applies actions to a
|Source||A function that creates an entirely new
|Action||An atomic operation to be validated and committed to a filesystem or a
|Sink||The final destination of all
Schematics is a library, and does not work by itself. A reference CLI is available on this repository, but is not published on NPM. This document explains the library usage and the tooling API, but does not go into the tool implementation itself.
The tooling is responsible for the following tasks:
- Create the Schematic Engine, and pass in a Collection and Schematic loader.
- Understand and respect the Schematics metadata and dependencies between collections. Schematics can refer to dependencies, and it's the responsibility of the tool to honor those dependencies. The reference CLI uses NPM packages for its collections.
- Create the Options object. Options can be anything, but the schematics can specify a JSON Schema that should be respected. The reference CLI, for example, parses the arguments as a JSON object and validates it with the Schema specified by the collection.
- Schematics provides some JSON Schema formats for validation that tooling should add. These validate paths, html selectors and app names. Please check the reference CLI for how these can be added.
- Call the schematics with the original Tree. The tree should represent the initial state of the filesystem. The reference CLI uses the current directory for this.
- Create a Sink and commit the result of the schematics to the Sink. Many sinks are provided by the library; FileSystemSink and DryRunSink are examples.
- Output any logs propagated by the library, including debugging information.
The tooling API is composed of the following pieces:
SchematicEngine is responsible for loading and constructing
Schematics. When creating an engine, the tooling provides an
EngineHost interface that understands how to create a
CollectionDescription from a name, and how to create a
Schematics are generators and part of a
A Collection is defined by a
collection.json file (in the reference CLI). This JSON defines the following properties:
||The name of the collection.|
Operators, Sources and Rules
Source is a generator of a
Tree; it creates an entirely new root tree from nothing. A
Rule is a transformation from one
Tree to another. A
Schematic (at the root) is a
Rule that is normally applied on the filesystem.
FileOperators apply changes to a single
FileEntry and return a new
FileEntry. The result follows these rules:
- If the
FileEntryreturned is null, a
DeleteActionwill be added to the action list.
- If the path changed, a
RenameActionwill be added to the action list.
- If the content changed, an
OverwriteActionwill be added to the action list.
It is impossible to create files using a
The Schematics library provides multiple
Operator factories by default that cover basic use cases:
||Apply a content template (see the Template section)|
||Apply a path template (see the Template section)|
The Schematics library additionally provides multiple
Source factories by default:
||Creates a source that returns an empty
||Loads a list of files from the given URL and returns a
||Apply a list of
The schematics library also provides
Rule factories by default:
||Returns the input
||Moves all the files from the input to a subdirectory.|
||Merge the input
||Apply a content template (see the Template section) to the entire
||Apply a path template (see the Template section) to the entire
||Apply both path and content templates (see the Template section) to the entire
||Returns the input
As referenced above, some functions are based upon a file templating system, which consists of path and content templating.
The system operates on placeholders defined inside files or their paths as loaded in the
Tree and fills these in as defined in the following, using values passed into the
Rule which applies the templating (i.e.
|variable||Replaced with the value of
|variable@function||Replaced with the result of the call
|<%- expression %>||Same as above, but the value of the result will be escaped for HTML when inserted (i.e. replacing '<' with '<')|
|<%# text %>||A comment, which gets entirely dropped.|
An example of a simple Schematics which creates a "hello world" file, using an option to determine its path:
A few things from this example:
- The function receives the list of options from the tooling.
- It returns a
Rule, which is a transformation from a
A simplified example of a Schematics which creates a file containing a new Class, using an option to determine its name:
Additional things from this example:
stringsprovides the used
classifyfunctions, among others.
- The files are on-disk in the same root directory as the
index.tsand loaded into a
- Then the
Rulefills in the specified templating placeholders. For this, it only knows about the variables and functions passed to it via the options-object.
- Finally, the resulting
Tree, containing the new file, is merged with the existing files of the project which the Schematic is run on.
Schematics is not done yet. Here's a list of things we are considering:
- Prompt for input options. This should only be prompted for the original schematics, dependencies to other schematics should not trigger another prompting.
- Tasks for running tooling-specific jobs before and after a schematics has been scaffolded. Such tasks can involve initialize git, or npm install. A specific list of tasks should be provided by the tool, with unsupported tasks generating an error.