ReviewOS

stacks/logsmith

generateChangelog() crashes on a partial config — does not merge defaults before reading array fields

#3397
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Symptom

Calling the programmatic generateChangelog() API with a partial config throws:

undefined is not an object (evaluating 'i.excludeCommitTypes.length')

This is how @stacksjs/bumpx calls it during a release — it passes only:

{ output: "CHANGELOG.md", cwd: t, from: i, to: D }

…no excludeCommitTypes, includeCommitTypes, etc. The function trusts the incoming object is a fully-populated LogsmithConfig and never merges defaultConfig, so the first array-field access blows up.

Observed live while releasing @stacksjs/logsmith@0.2.2: the release tagged + published to npm but produced no CHANGELOG entry because this threw (and bumpx's shell fallback is also broken — separate issue on stacksjs/bumpx).

Root cause

packages/logsmith/src/changelog.ts:23:

export async function generateChangelog(config: LogsmithConfig): Promise<ChangelogResult> {
  const { dir, from, to, output, verbose } = config
  // ... config is passed straight through, no defaults merged

It flows down to packages/logsmith/src/utils.ts:335:

function shouldExcludeCommit(commit: CommitInfo, config: LogsmithConfig): boolean {
  const type = commit.type || 'misc'
  if (config.excludeCommitTypes.length > 0 && config.excludeCommitTypes.includes(type)) {  // <-- throws when undefined

The type signature says LogsmithConfig (fully-populated), but every external caller realistically passes a partial. The CLI path works only because it builds a full config via loadLogsmithConfig first.

Fix

Merge defaults at the top of generateChangelog so the public API is partial-tolerant:

- export async function generateChangelog(config: LogsmithConfig): Promise<ChangelogResult> {
-   const { dir, from, to, output, verbose } = config
+ export async function generateChangelog(options: Partial<LogsmithConfig>): Promise<ChangelogResult> {
+   const config = { ...defaultConfig, ...options }
+   const { dir, from, to, output, verbose } = config

(defaultConfig already sets excludeCommitTypes: [] etc. in packages/logsmith/src/config.ts:23.)

Loosening the param type to Partial<LogsmithConfig> also makes the contract honest for programmatic callers like bumpx.

Sign in to comment on this issue.