@platform/tmpl
v0.1.78
Published
Succinct powerful template stamper.
Downloads
30
Readme
Succinct, composable, template stamping pipeline.
Think of it as your scaffolding superpower.
For the out-of-box CLI experience see create-tmpl:
yarn create tmpl
Setup
yarn install @platform/tmpl
Introduction
Compose directories and files together with glob patterns into a powerful Template
that can be copied anywhere...to the file-system, to memory, wherever.
Add simple middleware
functions to the pipeline to precisely customize each file as it is written, taking variable arguments (via the API) or values entered by the user (via the command-line).
Interfaces
Philosophy
The best programmers are lazy. If you do anything more than three times, it might be a good idea to automate it 🤖
The create-tmpl
module is here to make creating repeatable scaffolding through templates painless, powerful and low-effort. So low effort, in fact, you're more than likely to do it.
Design principles
- Lean on the file-system.
- Simple configuration (or "no-configuration").
- Beautiful command-line that's fast and fun to use.
- Powerful composability of source files (assemble base template and then make overriding variants).
- Elegant API for integrating into other modules.
- Pluggable middleware pipeline for extensibility.
Maxims
🌳 CLI
Installation
To use the tmpl
command-line across your machine install it globally:
yarn global add create-tmpl
then use tmpl
from any folder:
$ tmpl <command> [options]
$ tmpl --help
Local Module
To use the tmpl
command locally within your scripts, add it to your module:
yarn add create-tmpl
then invoke it from scripts
within your package.json
like so:
{
"name": "my-module",
"scripts": {
"postinstall": "tmpl ./node_modules/my-module/setup-template"
},
"dependencies": {
"create-tmpl": "latest"
}
}
Configuration
...TDB
Commands
...TDB
🌳 API
When working with a Template
you'll move through three stages:
- Template composition
- Filters and middleware processors.
- Execution
Templates are immutable, meaning any calls to the .add
, .filter
, .use
methods return a new instance of the Template
(conceptually similar to rxjs).
Composition (add source files)
A template is composed of one or more file locations consisting of a directory and an optional glob pattern (default is **
, everything).
import { Template } from 'create-tmpl';
const tmpl = Template.create()
.add({ dir: './templates/one' })
.add({ dir: './templates/two', pattern: '**/*.md' });
Template files that are added later which collide will override the earlier paths. Use this capability to create base template folders and then compose together more specialised templates that incrementally expand and alter the base set of files.
To see the resulting files that make up the template:
const files = await tmpl.files();
Filtering
Create a subset of the template using filters:
const markdown = tmpl.filter(file => file.path.endsWith('.md'));
const files = await markdown.files(); // Now only markdown files.
Middleware
A pipeline of middleware functions provide the mechanism for transforming templates and saving them to the file-system, or wherever you need to send the execution result. Template middleware is conceptually equivalent to express middleware:
import { template, path, fs } from 'create-tmpl';
type IMyVariables = { greeting: string };
const tmpl = template
.create()
.add({ dir: './tmpl-1' })
.add({ dir: './tmpl-2' })
// Transform the text content of files (naive example 🤭 ).
.use<IMyVariables>((req, res) => {
res.replaceText(/__GREETING__/g, req.variables.greeting).next(); // Signal to move to next middleware.
})
// Save the file to disk.
.use(async (req, res) => {
const dir = path.resolve('./output');
await fs.ensureDir(dir);
await fs.writeFile(path.join(dir, req.path), req.buffer);
// Signal the operation is complete (no more middleware will run).
res.complete();
});
Middleware is executed in the order that it is added to the pipeline. Call res.next()
to move to the next middleware in the pipeline, or call res.complete()
when done, and the execution pipeline finished.
const tmpl = Template.create('./my-tmpl').use(/\.ts$/, (req, res) => {
// Operate on typescript file only.
// ...
res.next();
});
When adding middleware you can optionally apply pathFilter
regular-expressions to narrow which file paths the middleware applies to. The example above operates on .ts
files only. Passing an array of regular-expressions acts as an OR
set.
Execution
We now have a configured template that will transform text files and save them to disk when executed.
Let's execute it passing in some variables:
const variables: IMyVariables = { greeting: 'Hello!' };
await tmpl.execute<IMyVariables>({ variables });