com um clique
pipeline-style
Use it when writing data pipelines
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Menu
Use it when writing data pipelines
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Baseado na classificação ocupacional SOC
| name | pipeline-style |
| description | Use it when writing data pipelines |
| version | 0.1.0 |
| user-invocable | true |
Pipeline style means writing code as a compact vocabulary of composable operations. Instead of building long procedural blocks, we define small, named operations and combine them into clear data-flow pipelines.
A pipeline should read as a sequence of transformations.
Prefer this:
const ExtractEntities = pipeline(
(name) => LoadFile(`src/json/ref-${name}.json`),
(_) => grouped(_, "fibery/id"),
(_) => map(_, ary(1, head)),
);
Avoid this:
async function ExtractEntities(name) {
const file = await LoadFile(`src/json/ref-${name}.json`);
const groups = grouped(file, "fibery/id");
const result = map(groups, ary(1, head));
return result;
}
The pipeline version makes the shape of the computation visible: load, group, select.
Pipeline code should rely on a small set of reusable operations such as (available in select.js utils):
map
filter
reduce
head
grouped
ary
pipeline
Agents should prefer existing vocabulary before introducing new helpers.
When adding a new operation, make sure it is:
Domain-level pipeline functions should use PascalCase because they behave like named nodes in a processing graph.
const LoadFile = (path) => Bun.file(path).json();
const ExtractEntities = pipeline(
(name) => LoadFile(`src/json/ref-${name}.json`),
(_) => grouped(_, "fibery/id"),
(_) => map(_, ary(1, head)),
);
Use PascalCase for operations such as:
LoadFile
ExtractEntities
ResolveReferences
BuildIndex
OutputConfiguration
Use lower-case names for generic utilities and local variables.
Each pipeline step should do one thing.
Good:
(_) => grouped(_, "fibery/id")
Less good:
(_) => map(grouped(_, "fibery/id"), ary(1, head))
Prefer clarity over cleverness. A pipeline is readable when each step has a clear purpose.
Comments should explain why the step exists or what role it plays in the pipeline.
Good:
const ExtractEntities = pipeline(
// Loads the JSON reference file
(name) => LoadFile(`src/json/ref-${name}.json`),
// Groups records by Fibery id
(_) => grouped(_, "fibery/id"),
// Keeps the first entity from each group
(_) => map(_, ary(1, head)),
);
Avoid comments that merely repeat syntax.
Bad:
// Calls grouped
(_) => grouped(_, "fibery/id")
pipeline handle async flowPipeline functions may contain async operations. Do not manually thread await through every step unless the surrounding API requires it.
Good:
const LoadFile = (path) => Bun.file(path).json();
const ExtractEntities = pipeline(
(name) => LoadFile(`src/json/ref-${name}.json`),
(_) => grouped(_, "fibery/id"),
(_) => map(_, ary(1, head)),
);
Callers should await the composed pipeline result:
console.log(await ExtractEntities("entities"));
_ for the current pipeline valueInside simple transformation steps, use _ to represent the value flowing through the pipeline.
(_) => grouped(_, "fibery/id")
Use a named parameter when the input has domain meaning.
(name) => LoadFile(`src/json/ref-${name}.json`)
This keeps generic transformations visually distinct from domain inputs.
Most pipeline steps should be pure transformations.
For side effects, yield commands instead of executing effects directly.
class Command {
constructor(name, args) {
this.name = name;
this.args = args;
}
}
function cmd(name, ...args) {
return new Command(name, args);
}
Commands describe effects without performing them immediately.
When a pipeline needs external effects, model those effects as yielded commands.
const OutputConfiguration = function* () {
const path = yield cmd("config", "data.path");
yield cmd("log", `Output path is ${path}`);
};
This allows the runtime to decide how commands are executed, cached, logged, replayed, mocked, or tested.
A pipeline may yield commands and still return a value.
The returned value is the result of the pipeline. Yielded commands are requests for effects.
const BuildOutput = function* () {
const path = yield cmd("config", "data.path");
yield cmd("log", `Output path is ${path}`);
return { path };
};
Command names should be compact strings that represent effect types.
Good:
cmd("config", "data.path")
cmd("log", "Done")
cmd("write", path, data)
cmd("read", path)
Avoid command names that encode too much behavior.
Bad:
cmd("read-config-path-and-log-output-folder")
The command name should identify the kind of effect. The arguments should provide the details.
Commands create a boundary between the pipeline and the outside world.
This makes it possible to:
Agents should prefer yielded commands whenever an operation touches IO, configuration, logging, network, databases, files, or environment state.
Use pipelines for multi-step transformations:
const BuildIndex = pipeline(
(_) => grouped(_, "type"),
(_) => map(_, ary(1, head)),
);
Name domain operations clearly:
const ExtractEntities = pipeline(...);
const ResolveLinks = pipeline(...);
const BuildOutput = pipeline(...);
Use commands for effects:
yield cmd("log", "Starting export");
yield cmd("write", path, data);
Keep steps readable:
(_) => filter(_, isActive)
(_) => map(_, toEntity)
(_) => grouped(_, "id")
Avoid deeply nested expressions:
(_) => map(grouped(filter(_, isActive), "id"), toEntity)
Avoid mixing side effects into transformations:
(_) => {
console.log(_);
return _;
}
Prefer:
yield cmd("log", value);
Avoid large anonymous functions inside pipelines. Extract them into named operations instead.
const NormalizeEntity = (_) => ({
id: _["fibery/id"],
name: _.name,
});
const NormalizeEntities = pipeline(
(_) => map(_, NormalizeEntity),
);
A good pipeline module usually has this shape:
import {
map,
filter,
reduce,
head,
pipeline,
grouped,
ary,
} from "@select/utils";
const LoadFile = (path) => Bun.file(path).json();
const NormalizeEntity = (_) => ({
id: _["fibery/id"],
name: _.name,
});
const ExtractEntities = pipeline(
// Loads the JSON reference file
(name) => LoadFile(`src/json/ref-${name}.json`),
// Groups records by Fibery id
(_) => grouped(_, "fibery/id"),
// Keeps one entity per Fibery id
(_) => map(_, ary(1, head)),
// Normalizes entity shape
(_) => map(_, NormalizeEntity),
);
Think of pipeline style as building a graph of named processing nodes.
Each operation should answer one of these questions:
The best pipeline code reads almost like a table of contents for the computation.