@hyperfrontend/versioning/flow/models

models

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

§function

addStep(flow: VersionFlow, step: FlowStep): VersionFlow

Adds a step to a flow. Returns a new flow with the step appended.
Parameters
NameTypeDescription
§flow
VersionFlowThe flow to extend
§step
FlowStepThe step to add
Returns
VersionFlow
A new VersionFlow with the step added
Example

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 + 1
§function

createFailedResult(error: Error, message?: string): FlowStepResult

Creates a failed step result.
Parameters
NameTypeDescription
§error
ErrorError that caused the failure
§message?
stringOptional message (defaults to error.message)
Returns
FlowStepResult
A FlowStepResult with 'failed' status
Example

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')
}
§function

createFlow(id: string, name: string, steps: unknown, options: CreateFlowOptions): VersionFlow

Creates a version flow.
Parameters
NameTypeDescription
§id
stringFlow identifier
§name
stringHuman-readable flow name
§steps
unknownOrdered steps to execute
§options
CreateFlowOptionsOptional flow configuration(default: {})
Returns
VersionFlow
A VersionFlow object
Example

Creating a custom flow

const myFlow = createFlow(
  'custom',
  'Custom Release Flow',
  [fetchStep, analyzeStep, bumpStep],
  { description: 'My custom versioning workflow' }
)
§function

createNoopStep(id: string, name: string, message: string): FlowStep

Creates a step that succeeds immediately. Useful for placeholder or conditional steps.
Parameters
NameTypeDescription
§id
stringUnique identifier within the flow
§name
stringDisplay label shown during execution
§message
stringSuccess message(default: 'Step completed (no-op)')
Returns
FlowStep
A FlowStep that always succeeds
Example

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'
§function

createSkippedResult(message: string): FlowStepResult

Creates a skipped step result.
Parameters
NameTypeDescription
§message
stringExplanation for why the step was skipped
Returns
FlowStepResult
A FlowStepResult with 'skipped' status
Example

Skipping a step conditionally

import { createSkippedResult } from '@hyperfrontend/versioning'

// In a step handler:
if (!config.enabled) {
  return createSkippedResult('Feature disabled in config')
}
§function

createStep(id: string, name: string, execute: StepExecutor, options: CreateStepOptions): FlowStep

Creates a flow step.
Parameters
NameTypeDescription
§id
stringUnique step identifier
§name
stringHuman-readable step name
§execute
StepExecutorStep executor function
§options
CreateStepOptionsOptional step configuration(default: {})
Returns
FlowStep
A FlowStep object
Example

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}`
    }
  }
)
§function

createSuccessResult(message: string, stateUpdates?: Partial<FlowState>): FlowStepResult

Creates a success step result.
Parameters
NameTypeDescription
§message
stringOutput text describing what the step accomplished
§stateUpdates?
Partial<FlowState>Optional state updates to apply after step completion
Returns
FlowStepResult
A FlowStepResult with 'success' status
Example

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']
})
§function

getStep(flow: VersionFlow, stepId: string): FlowStep

Gets a step from a flow by ID.
Parameters
NameTypeDescription
§flow
VersionFlowThe flow to search
§stepId
stringThe step ID to find
Returns
FlowStep
The step if found, undefined otherwise
Example

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'
§function

hasStep(flow: VersionFlow, stepId: string): boolean

Checks if a flow has a specific step.
Parameters
NameTypeDescription
§flow
VersionFlowThe flow to check
§stepId
stringThe step ID to look for
Returns
boolean
True if the flow contains the step
Example

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'))
// => false
§function

insertStep(flow: VersionFlow, step: FlowStep, index: number): VersionFlow

Inserts a step at a specific position.
Parameters
NameTypeDescription
§flow
VersionFlowThe flow to modify
§step
FlowStepThe step to insert
§index
numberPosition to insert at (0-based)
Returns
VersionFlow
A new VersionFlow with the step inserted
Example

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'
§function

insertStepAfter(flow: VersionFlow, step: FlowStep, afterStepId: string): VersionFlow

Inserts a step after another step.
Parameters
NameTypeDescription
§flow
VersionFlowThe flow to modify
§step
FlowStepThe step to insert
§afterStepId
stringID of the step to insert after
Returns
VersionFlow
A new VersionFlow with the step inserted
Example

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'
§function

insertStepBefore(flow: VersionFlow, step: FlowStep, beforeStepId: string): VersionFlow

Inserts a step before another step.
Parameters
NameTypeDescription
§flow
VersionFlowThe flow to modify
§step
FlowStepThe step to insert
§beforeStepId
stringID of the step to insert before
Returns
VersionFlow
A new VersionFlow with the step inserted
Example

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'
§function

removeStep(flow: VersionFlow, stepId: string): VersionFlow

Removes a step from a flow by ID. Returns a new flow without the specified step.
Parameters
NameTypeDescription
§flow
VersionFlowThe flow to modify
§stepId
stringThe ID of the step to remove
Returns
VersionFlow
A new VersionFlow without the step
Example

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'))
// => undefined
§function

replaceStep(flow: VersionFlow, stepId: string, newStep: FlowStep): VersionFlow

Replaces a step in the flow.
Parameters
NameTypeDescription
§flow
VersionFlowThe flow to modify
§stepId
stringID of the step to replace
§newStep
FlowStepThe replacement step
Returns
VersionFlow
A new VersionFlow with the step replaced
Example

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 implementation
§function

withConfig(flow: VersionFlow, config: Partial<FlowConfig>): VersionFlow

Updates the flow configuration.
Parameters
NameTypeDescription
§flow
VersionFlowThe flow to configure
§config
Partial<FlowConfig>Configuration updates to merge
Returns
VersionFlow
A new VersionFlow with updated config
Example

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

§interface

CreateFlowOptions

Options for creating a version flow.
Properties
§description?:stringFlow description
§config?:FlowConfigFlow configuration
§interface

CreateStepOptions

Options for creating a flow step.
Properties
§description?:stringStep description
§skipIf?:StepConditionCondition for skipping step
§continueOnError?:booleanWhether step failure should fail the flow
§dependsOn?:unknownSteps that must complete before this one
§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.
§interface

FlowConfig

Flow configuration options.
Properties
§readonly preset?:"conventional" | "independent" | "synced"Preset name or custom configuration
§readonly releaseTypes?:unknownCommit types that trigger releases
§readonly minorTypes?:unknownCommit types that trigger minor bumps
§readonly patchTypes?:unknownCommit types that trigger patch bumps
§readonly skipGit?:booleanSkip git operations
§readonly skipTag?:booleanSkip tag creation
§readonly skipChangelog?:booleanSkip changelog update
§readonly dryRun?:booleanDry run mode - preview changes without applying
§readonly commitMessage?:stringCustom commit message template
§readonly tagFormat?:stringCustom tag format
§readonly trackDeps?:booleanTrack dependencies for cascade bumps
§readonly releaseBranch?:stringBranch allowed for releases
§readonly firstReleaseVersion?:stringBase version for first release
§readonly allowPrerelease?:booleanAllow prerelease versions
§readonly prereleaseId?:stringPrerelease identifier (e.g., 'alpha', 'beta')
§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 remote
  • RepositoryResolution: Fine-grained control with explicit mode and options
  • RepositoryConfig: 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 changelogFileName?:stringChangelog file name relative to project root.
§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:
  1. Existing CHANGELOG.md is renamed to CHANGELOG.backup.md
  2. New changelog is written
  3. Backup is deleted on success
Useful for safety during changelog regeneration.
§interface

FlowContext

Execution context passed to each step. Contains all resources and accumulated state.
Note: state is mutable within context to allow accumulation, but individual FlowState objects are immutable.
Properties
§readonly workspaceRoot:stringWorkspace root path
§readonly projectName:stringTarget project name
§readonly projectRoot:stringProject root path
§readonly packageName:stringPackage name from package.json
§readonly tree:TreeVirtual file system tree
§readonly registry:RegistryRegistry client
§readonly git:GitClientGit client
§readonly logger:LoggerLogger instance
§readonly config:FlowConfigFlow configuration
§state:FlowStateAccumulated state from previous steps (mutable reference)
§interface

FlowResult

Complete result of flow execution.
Properties
§readonly status:FlowStatusOverall flow outcome
§readonly steps:unknownResults for each step
§readonly state:FlowStateFinal accumulated state
§readonly duration:numberDuration in milliseconds
§readonly summary:stringSummary message
§readonly modifiedFiles?:unknownFiles that were modified (or would be in dry-run)
§readonly diffs?:unknownDetailed diffs for pending changes. Populated when showDiff: true is passed to executeFlow. Provides unified diff format for programmatic access.
§interface

FlowState

Accumulated state during flow execution. Each step can read previous state and contribute updates.
Properties
§readonly currentVersion?:stringCurrent/local version from package.json
§readonly publishedVersion?:stringPublished version on registry (null if never published)
§readonly publishedCommit?:stringGit commit hash of the last published version
§readonly nextVersion?:stringCalculated next version
§readonly bumpType?:BumpTypeBump type (major/minor/patch/none)
§readonly commits?:unknownAnalyzed commits since last release
§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 changelogEntry?:ChangelogEntryGenerated changelog entry
§readonly modifiedFiles?:unknownFiles modified during flow execution
§readonly commitHash?:stringCreated git commit hash
§readonly tagName?:stringCreated git tag name
§readonly isFirstRelease?:booleanWhether this is a first release (no prior versions)
§readonly repositoryConfig?:RepositoryConfigRepository configuration for compare URL generation
§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
§interface

FlowStep

A single step in a version flow.
Steps are pure functions that:
  1. Read from context (state, config, services)
  2. Perform work (possibly with side effects via services)
  3. Return state updates
Properties
§readonly id:stringStep identifier (unique within flow)
§readonly name:stringHuman-readable step name
§readonly description?:stringOptional step description
§readonly execute:StepExecutorStep function to execute
§readonly skipIf?:StepConditionCondition for skipping step
§readonly continueOnError?:booleanWhether step failure should fail the flow
§readonly dependsOn?:unknownSteps that must complete before this one
§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.
§interface

FlowStepResult

Result of a single step execution.
Properties
§readonly status:"success" | "skipped" | "failed"Step outcome
§readonly stateUpdates?:Partial<FlowState>State updates from this step
§readonly message?:stringDescriptive message
§readonly error?:ErrorError if failed
§interface

FlowStepResultWithId

Step result with step identification.
Properties
§readonly status:"success" | "skipped" | "failed"Step outcome
§readonly stateUpdates?:Partial<FlowState>State updates from this step
§readonly message?:stringDescriptive message
§readonly error?:ErrorError if failed
§readonly stepId:stringStep identifier
§readonly stepName:stringStep display name
§interface

Logger

Logger interface with level-specific methods and level control
Properties
§log:LogLevelFnStandard log output
§warn:WarnLevelFnWarning-level output
§error:ErrorLevelFnError-level output
§info:InfoLevelFnInfo-level output
§debug:DebugLevelFnDebug-level output
§setLogLevel:SetLogLevelSets the current log level
§getLogLevel:GetLogLevelGets the current log level
§channel:ChannelFnReturns a sub-logger that prepends [prefix] to every message.
§timed:TimedFnWraps a sync call with timing. Logs completion or failure with elapsed ms.
§timedAsync:TimedAsyncFnWraps a promise-returning call with timing. Dumps stack trace on error to debug log.
§interface

VersionFlow

A complete version flow definition.
Flows are immutable configurations that define:
  1. What steps to execute
  2. In what order
  3. With what configuration
Properties
§readonly id:stringFlow identifier
§readonly name:stringHuman-readable flow name
§readonly description?:stringFlow description
§readonly steps:unknownOrdered steps to execute
§readonly config:FlowConfigFlow-level configuration

◆ Types

§type

FlowStatus

Overall flow execution status.
type FlowStatus = "success" | "partial" | "failed" | "skipped"
§type

StepCondition

Step skip condition function type. Returns true if the step should be skipped.
type StepCondition = (context: FlowContext) => boolean
§type

StepExecutor

Step executor function type. Takes flow context and returns a step result promise.
type StepExecutor = (context: FlowContext) => Promise<FlowStepResult>

● Variables

§type

DEFAULT_CHANGELOG_FILENAME

Default changelog filename.
§type

DEFAULT_FLOW_CONFIG

Default flow configuration values.