Skip to content

Inputs

An Input defines a standalone function to provide any dynamic data needed to inform production. Unlike Blocks and Presets, Inputs are not bound to any one Base. Inputs may be shared and used freely within production functions.

The kinds of dynamic data sourced by Inputs often include:

  • Files on disk, such as raw text or parsed .json
  • Sending network requests
  • Running terminal commands, such as npm whoami

create will manage providing inputs with a runtime Context containing a file system, network fetcher, and shell runner.

Production

Inputs define their logic for reading data in a produce() function.

For example, an input that retrieves the current running time:

import { createInput } from "create";
export const inputNow = createInput({
produce() {
return performance.now();
},
});

Later on, a Block could use that input to retrieve the current running time:

import { base } from "./base";
import { inputNow } from "./inputNow";
export const blockUsingNow = base.createBlock({
produce({ take }) {
const now = take(inputNow);
return {
files: {
"last-touch.txt": now.toString(),
},
};
},
});

That block would instruct create to create a last-touch.txt file with the current performance.now() timestamp when run.

Context

Inputs have access to the shared Context managed by create. They can use that Context to access the file system, execute shell scripts, or other system interactions.

For example, a block that uses the Context’s runner to execute npm whoami:

import { createInput } from "create";
export const inputNpmWhoami = createInput({
produce({ runner }) {
return (await runner("npm whoami")).stdout;
},
});

That Input can then be used by later Blocks and/or Inputs to retrieve the logged-in npm user, if one exists.

Args

Inputs being standalone means they have no access to Base Options. Instead, Inputs may define and take in their own Args.

Inputs describe those Args as the properties of a Zod object base. That allows them validate provided values and infer types from an args property in their context.

For example, an input that retrieves JSON data from a file on disk using the provided virtual file system:

import { createInput } from "create";
import { z } from "zod";
export const inputJSONFile = createInput({
args: {
fileName: z.string(),
},
async produce({ args, fs }) {
try {
return JSON.parse((await fs.readFile(args.fileName)).toString());
} catch {
return undefined;
}
},
});

Later on, take calls to the Input will be able to provide those Args.

Composition

Inputs are composable: meaning each can take data from other Inputs. As with Blocks, the Context provided to Inputs includes a take function that calls to another Input.

For example, an Input that determines the npm username based on either npm whoami or package.json Inputs:

import { createInput } from "create";
import { inputJSONFile } from "./inputJsonData";
import { inputNpmWhoami } from "./inputNpmWhoami";
export const inputNpmUsername = createInput({
async produce({ take }) {
return (
(await take(inputNpmWhoami)) ??
(await take(inputJSONFile, { fileName: "package.json" })).author
);
},
});

Provided Inputs

create manages a small set of commonly useful Inputs:

See those individual packages for their documentation.

APIs