createBase
The Stratum engine provides a createBase
method to create the starting Base object for a template.
That object provides granular APIs for each of the layers:
createBlock
: creates a new Block for the BasecreatePreset
: creates a new Preset for the BasecreateTemplate
: creates a new Template for the Base
createBase
Given a Base Definition, creates a Base.
A Base Definition is an object containing:
options
(required): a Base Options object containing Zod valuesprepare
(optional): a Base preparation function to fill in default options
options
The Zod values for options that will be made available to the Base and all its Blocks.
For example, this Base defines a required name
string and optional value
number:
import { createBase } from "bingo-stratum";
export const base = createBase({ options: { name: z.string(), value: z.number().optional(), },});
prepare
A Base may define a prepare
function to fill in any values that aren’t inferred by the system at runtime.
prepare()
functions receive an Options Context parameter.
They must return an object whose properties fill in any options that can be inferred from the system.
Each property may either be a value or an asynchronous function to retrieve that value.
For example, this Base allows defaulting a required name
option to that property of its package.json
using [input-from-file-json
]
import { createBase } from "bingo-stratum";import { inputFromFileJSON } from "input-from-file-json";import { z } from "zod";
export const base = createBase({ options: { name: z.string(), }, prepare({ take }) { return { name: async () => (await take(inputFromFileJSON, { fileName: "package.json" })).name, }; },});
createBlock
Blocks can be created by the createBlock()
function of a Base.
createBlock()
takes in a Block Definition and returns a Block.
A Block Definition is an object containing:
about
(optional): tooling metadata for the Blockproduce
(required): a Block production method
about
Metadata about the Block that can be used by tooling to describe it.
This is an object containing any of:
description
: a sentence describing what the Block doesname
: what to refer to the Block as
For example, this Block describes itself as setting up monorepo TypeScript building:
import { base } from "./base";
base.createBlock({ about: { description: "TSConfigs and build tasks for a monorepo.", name: "TypeScript Builds", }, produce() { // ... },});
addons
Block Definitions may include an addons
object defining Zod values as its properties.
Whenever a new instance of a Block with args is constructed, those Addons must be provided to it.
For example, this Prettier block optionally allows adding in any plugins with a plugins
arg:
import { z } from "zod";
import { base } from "./base";
export const blockPrettier = base.createBlock({ args: { plugins: z.array(z.string()).optional(), }, async produce({ args }) { return { files: { ".prettierrc.json": args.plugins && JSON.stringify({ $schema: "http://json.schemastore.org/prettierrc", plugins: args.plugins, }), }, }; },});
See Stratum > Concepts > Blocks > Addons for more information.
produce
Block Definitions must include a produce()
function for their core logic.
- It receives one parameter: a Block Context object containing options as well as other utilities.
- It returns a Creation object describing the generated pieces of tooling.
For example, this Block defines a files
Creation for a knip.json
:
import { base } from "./base";
export const blockKnip = base.createBlock({ produce() { return { files: { "knip.json": JSON.stringify({ $schema: "https://unpkg.com/knip@latest/schema.json", }), }, }; },});
createPreset
Presets can be created by the createPreset()
function of a Base.
createPreset()
takes in a Preset Definition and returns a Preset.
A Preset Definition is an object containing:
about
(optional): tooling metadata for the Presetblocks
(required): any number of Blocks run by the Preset
about
Metadata about the Preset that can be used by tooling to describe it.
This is an object containing any of:
description
: a sentence describing what the Preset doesname
: what to refer to the Preset as
For example, this Preset describes itself as setting up a bare-bones TypeScript monorepo:
import { base } from "./base";
base.createPreset({ about: { description: "The barest of bones tooling for a type-safe monorepo.", name: "Minimal", }, blocks: [ // ... ],});
blocks
The Blocks that will be run to generate the Preset’s Creations during production.
For example, this Preset includes blocks for building and testing:
import { base } from "./base";import { blockBuilds } from "./blockBuilds";import { blockTests } from "./blockTests";
base.createPreset({ blocks: [blockBuilds, blockTests],});
The Blocks provided to a Preset must be created from the same root Base.
createTemplate
Templates can be created by the createTemplate()
function of a Base.
createTemplate()
takes in a Template Definition and returns a Template.
A Template Definition is an object containing:
about
(optional): tooling metadata for the Templatepresets
(required): an array of objects for the Presets available with the Templatesuggested
(optional): Which Preset should be selected by default in CLIs
about
Metadata about the template that can be used by tooling to describe it.
This is an object containing any of:
description
: a sentence describing what the template doesname
: what to refer to the template asrepository
: theowner
andrepository
of a GitHub Template Repository
For example, this Template describes itself as a solution for TypeScript repositories:
import { base } from "./base";
base.createTemplate({ about: { description: "One-stop shop for the latest and greatest TypeScript tooling.", name: "Create TypeScript App", repository: { owner: "JoshuaKGoldberg", repository: "create-typescript-app", }, }, presets: [ // ... ],});
Repositories generated from that template would indicate generated from JoshuaKGoldberg/create-typescript-app under their name on the GitHub website.
presets
The Presets users can choose from with the Template, in order of how they should be listed.
Each element in the array is an object containing:
label
(required): a brief name for the Preset for text displayspreset
(required): the Preset itself
For example, this Template allows choosing between two Presets for TypeScript apps:
import { base } from "./base";import { presetCommon } from "./presetCommon";import { presetEverything } from "./presetEverything";
export const templateTypeScriptApp = base.createTemplate({ about: { name: "TypeScript App", }, presets: [ { label: "Common", preset: presetCommon }, { label: "Everything", preset: presetEverything }, ],});
suggested
The suggested Preset to select for users, if not the first in the array.
This should be the same string as one of the labels
under presets
.
For example, this Template defaults to the "Common"
Preset:
import { base } from "./base";import { presetCommon } from "./presetCommon";import { presetEverything } from "./presetEverything";
export const templateTypeScriptApp = base.createTemplate({ presets: [ { label: "Common", preset: presetCommon }, { label: "Everything", preset: presetEverything }, ], suggested: presetCommon,});