@hyperfrontend/versioning/flow/modelsmodels
Type definitions and immutable builders for version flows and their steps.
VersionFlow is the top-level shape carrying steps, configuration, and metadata; FlowStep is the per-step shape carrying an ID, a condition, and an executor. createFlow, addStep, removeStep, insertStep, insertStepAfter, and insertStepBefore are the immutable builders: every operation returns a new VersionFlow rather than mutating in place. FlowConfig, FlowContext, FlowResult, FlowState, FlowStatus, FlowStepResult, and FlowStepResultWithId describe the runtime surface that the executor threads through each step.
API Reference§
ƒ Functions
Parameters
| Name | Type | Description |
|---|---|---|
§flow | VersionFlow | The flow to extend |
§step | FlowStep | The step to add |
Returns
VersionFlowExample
Adding a custom step to a flow
import { addStep, createConventionalFlow, createNoopStep } from '@hyperfrontend/versioning'
const flow = createConventionalFlow()
const extended = addStep(flow, createNoopStep('custom', 'Custom Step'))
console.log(extended.steps.length)
// => original steps + 1Parameters
Returns
FlowStepResultExample
Handling step execution errors
import { createFailedResult } from '@hyperfrontend/versioning'
// In a step handler:
try {
await doOperation()
} catch (err) {
return createFailedResult(err as Error, 'Operation failed')
}createFlow( id: string, name: string, steps: unknown, options: CreateFlowOptions): VersionFlow
Parameters
| Name | Type | Description |
|---|---|---|
§id | string | Flow identifier |
§name | string | Human-readable flow name |
§steps | unknown | Ordered steps to execute |
§options | CreateFlowOptions | Optional flow configuration(default: {}) |
Returns
VersionFlowExample
Creating a custom flow
const myFlow = createFlow(
'custom',
'Custom Release Flow',
[fetchStep, analyzeStep, bumpStep],
{ description: 'My custom versioning workflow' }
)Parameters
Returns
FlowStepExample
Creating a placeholder step
import { createNoopStep, executeStep } from '@hyperfrontend/versioning'
const step = createNoopStep('placeholder', 'Placeholder Step')
const result = await executeStep(step, context)
console.log(result.status)
// => 'success'Parameters
| Name | Type | Description |
|---|---|---|
§message | string | Explanation for why the step was skipped |
Returns
FlowStepResultExample
Skipping a step conditionally
import { createSkippedResult } from '@hyperfrontend/versioning'
// In a step handler:
if (!config.enabled) {
return createSkippedResult('Feature disabled in config')
}createStep( id: string, name: string, execute: StepExecutor, options: CreateStepOptions): FlowStep
Parameters
| Name | Type | Description |
|---|---|---|
§id | string | Unique step identifier |
§name | string | Human-readable step name |
§execute | StepExecutor | Step executor function |
§options | CreateStepOptions | Optional step configuration(default: {}) |
Returns
FlowStepExample
Creating a custom fetch step
const fetchStep = createStep(
'fetch-registry',
'Fetch Registry Version',
async (ctx) => {
const version = await ctx.registry.getLatestVersion(ctx.packageName)
return {
status: 'success',
stateUpdates: { publishedVersion: version },
message: `Found published version: ${version}`
}
}
)Parameters
Returns
FlowStepResultExample
Returning a success result with state updates
import { createSuccessResult } from '@hyperfrontend/versioning'
// In a step handler:
return createSuccessResult('Updated 3 files', {
modifiedFiles: ['/path/a.ts', '/path/b.ts', '/path/c.ts']
})Parameters
| Name | Type | Description |
|---|---|---|
§flow | VersionFlow | The flow to search |
§stepId | string | The step ID to find |
Returns
FlowStepExample
Getting a step by ID
import { getStep, createConventionalFlow } from '@hyperfrontend/versioning'
const flow = createConventionalFlow()
const step = getStep(flow, 'analyze-commits')
console.log(step?.name)
// => 'Analyze Commits'Parameters
| Name | Type | Description |
|---|---|---|
§flow | VersionFlow | The flow to check |
§stepId | string | The step ID to look for |
Returns
booleanExample
Checking if a flow has a step
import { hasStep, createConventionalFlow } from '@hyperfrontend/versioning'
const flow = createConventionalFlow()
console.log(hasStep(flow, 'create-commit'))
// => true
console.log(hasStep(flow, 'custom-step'))
// => falseParameters
| Name | Type | Description |
|---|---|---|
§flow | VersionFlow | The flow to modify |
§step | FlowStep | The step to insert |
§index | number | Position to insert at (0-based) |
Returns
VersionFlowExample
Inserting a step at a specific position
import { insertStep, createConventionalFlow, createNoopStep } from '@hyperfrontend/versioning'
const flow = createConventionalFlow()
const modified = insertStep(flow, createNoopStep('early', 'Early Step'), 0)
console.log(modified.steps[0].id)
// => 'early'Parameters
| Name | Type | Description |
|---|---|---|
§flow | VersionFlow | The flow to modify |
§step | FlowStep | The step to insert |
§afterStepId | string | ID of the step to insert after |
Returns
VersionFlowExample
Inserting a step after another step
import { insertStepAfter, createConventionalFlow, createNoopStep } from '@hyperfrontend/versioning'
const flow = createConventionalFlow()
const modified = insertStepAfter(flow, createNoopStep('validate', 'Validate'), 'analyze-commits'))
// 'validate' step now follows 'analyze-commits'Parameters
| Name | Type | Description |
|---|---|---|
§flow | VersionFlow | The flow to modify |
§step | FlowStep | The step to insert |
§beforeStepId | string | ID of the step to insert before |
Returns
VersionFlowExample
Inserting a step before another step
import { insertStepBefore, createConventionalFlow, createNoopStep } from '@hyperfrontend/versioning'
const flow = createConventionalFlow()
const modified = insertStepBefore(flow, createNoopStep('prep', 'Prepare'), 'create-commit'))
// 'prep' step now runs before 'create-commit'Parameters
| Name | Type | Description |
|---|---|---|
§flow | VersionFlow | The flow to modify |
§stepId | string | The ID of the step to remove |
Returns
VersionFlowExample
Removing a step from a flow
import { removeStep, createConventionalFlow } from '@hyperfrontend/versioning'
const flow = createConventionalFlow()
const minimal = removeStep(flow, 'generate-changelog')
// Flow no longer has changelog step
console.log(minimal.steps.find(s => s.id === 'generate-changelog'))
// => undefinedParameters
| Name | Type | Description |
|---|---|---|
§flow | VersionFlow | The flow to modify |
§stepId | string | ID of the step to replace |
§newStep | FlowStep | The replacement step |
Returns
VersionFlowExample
Replacing a step with a custom implementation
import { replaceStep, createConventionalFlow, createNoopStep } from '@hyperfrontend/versioning'
const flow = createConventionalFlow()
const modified = replaceStep(flow, 'create-tag', createNoopStep('create-tag', 'Custom Tag'))
// 'create-tag' now uses custom implementationParameters
| Name | Type | Description |
|---|---|---|
§flow | VersionFlow | The flow to configure |
§config | Partial< | Configuration updates to merge |
Returns
VersionFlowExample
Updating flow configuration
import { withConfig, createConventionalFlow } from '@hyperfrontend/versioning'
const flow = createConventionalFlow()
const dryRunFlow = withConfig(flow, { dryRun: true })
// Flow now runs in dry-run mode◈ Interfaces
Properties
Properties
requiresDiskFlush?:booleanWhether pending file writes must reach disk before this step runs. Steps that shell out to another tool, such as staging files for a commit, observe the real filesystem rather than the in-memory tree, so they see nothing until the tree is flushed.
Properties
readonly releaseAs?:"minor" | "patch" | "major"Force a specific bump type. The bump no longer comes from the commits, but they are still analyzed, and every commit type is admitted so the changelog lists what changed since the last release rather than only what could have caused a bump.readonly maxCommitFallback?:numberMaximum commits to analyze when no base commit is available. Used for first releases, history rewrites, and path-filtered queries. Set higher if you expect >500 commits between releases.
readonly repository?:RepositoryConfig | "inferred" | "disabled" | RepositoryResolutionRepository resolution configuration for compare URL generation. Controls how repository information is resolved:
'disabled': No compare URLs generated (default, backward compatible)'inferred': Auto-detect from package.json or git remoteRepositoryResolution: Fine-grained control with explicit mode and optionsRepositoryConfig: Direct repository configuration
readonly scopeFiltering?:ScopeFilteringConfigCommit scope filtering configuration. Controls how commits are attributed to projects in changelogs. By default, hybrid filtering ensures commits are included based on conventional commit scope OR file changes within the project.
readonly commitTypeToSection?:Partial< Record< string, ChangelogSectionType | null>>Custom mapping from commit type to changelog section. Merged with defaults; use null to exclude a type from changelog.readonly backupChangelog?:booleanCreate a backup of the existing changelog before modification. When enabled:
- Existing
CHANGELOG.mdis renamed toCHANGELOG.backup.md - New changelog is written
- Backup is deleted on success
Note:
state is mutable within context to allow accumulation, but individual FlowState objects are immutable.Properties
Properties
readonly diffs?:unknownDetailed diffs for pending changes. Populated when showDiff: true is passed to executeFlow. Provides unified diff format for programmatic access.Properties
readonly classificationResult?:ClassificationResultClassification result with source attribution (when scope filtering enabled)readonly effectiveBaseCommit?:stringThe verified base commit used for commit scoping and changelog generation. This will be publishedCommit if that commit is reachable from HEAD, or null if a fallback was used (e.g., history was rewritten). When null, compare URLs are omitted from the changelog.
readonly isPendingPublication?:booleanWhether this is a pending publication scenario. True when currentVersion > publishedVersion, meaning the version was already bumped but not yet published to the registry. When true: - nextVersion is calculated from publishedVersion (not currentVersion)
- Changelog entries > publishedVersion should be cleaned up
- The correct changelog entry replaces any stacked ones
Steps are pure functions that:
- Read from context (state, config, services)
- Perform work (possibly with side effects via services)
- Return state updates
Properties
readonly requiresDiskFlush?:booleanWhether pending file writes must reach disk before this step runs. Steps that shell out to another tool, such as staging files for a commit, observe the real filesystem rather than the in-memory tree, so they see nothing until the tree is flushed.
Properties
Properties
Properties
timedAsync:TimedAsyncFnWraps a promise-returning call with timing. Dumps stack trace on error to debug log.Flows are immutable configurations that define:
- What steps to execute
- In what order
- With what configuration
Properties
◆ Types
type FlowStatus = "success" | "partial" | "failed" | "skipped"type StepCondition = ( context: FlowContext) => booleantype StepExecutor = ( context: FlowContext) => Promise< FlowStepResult>