Skip to content

defineConfig and mergeConfig vanished from stryker-js/config in 11.0.0 #104

Description

@systemfsoftware-maker

Problem Statement

Upgrading @systemfsoftware/stryker-js from 10.x to 11.0.0 breaks every stryker.config.ts that follows the documented 10.x pattern: import { defineConfig } from '@systemfsoftware/stryker-js/config' now fails at load time, so the run dies before it reads a single option. The 11.0.0 CHANGELOG lists only a patch fix, so nothing tells the user why. The replacement, StrykerConfig.define(…) / StrykerConfig.merge(…), is more Effect-like, but it breaks the ergonomics every JS tool config shares (defineConfig / mergeConfig from Vite, Vitest, tsdown, oxlint), and it changes what the StrykerConfig type means, so the common const config: StrykerConfig = defineConfig({…}) annotation breaks too. The 10.x ./config surface should come back.

Goal

The next published @systemfsoftware/stryker-js release exports defineConfig and mergeConfig from ./config with their 10.1.1 signatures and exports StrykerConfig as the partial-options type, so a stryker.config.ts written against 10.1.1's ./config surface typechecks and loads without edits.

Evidence

A consumer config unchanged from 10.x, loaded by 11.0.0 (dry run through @systemfsoftware/stryker-js/promises):

_tag: 'ConfigFileUnreadableError',
file: 'stryker.config.ts',
  message: 'Failed to import module "file:///…/packages/effect-readiness/stryker.config.ts"',
  cause: …/effect-readiness/stryker.config.ts:2
  import { defineConfig,                    } from '@systemfsoftware/stryker-js/config'
           ^^^^^^^^^^^^
  SyntaxError: The requested module '@systemfsoftware/stryker-js/config' does not provide an export named 'defineConfig'

The published ./config declarations, 10.1.1 against 11.0.0:

// 10.1.1 dist/config.d.mts:10-23
type StrykerConfig = PartialStrykerOptions;
export declare function defineConfig(config: StrykerConfig): StrykerConfig;
export declare const mergeConfig: (defaults: StrykerConfig, overrides: StrykerConfig) => StrykerConfig;
export type { ConfigEnv, PartialStrykerOptions, StrykerConfig, StrykerConfigExport, StrykerConfigFn, StrykerOptions };

// 11.0.0 dist/config.d.mts:7 and dist/stryker-config.schema-lr7GMjpY.d.mts:17-21
export { type ConfigEnv, type Immutable, type ImmutablePrimitive, type Primitive, StrykerConfig, type StrykerConfigExport, type StrykerConfigFn };
declare const StrykerConfig_base: S.Class<StrykerConfig, S.Struct<{ readonly entries: S.$Record<S.String, S.Unknown> }>, {}>;
declare class StrykerConfig extends StrykerConfig_base {
  static define(config: mod_d_exports$2.PartialStrykerOptions): mod_d_exports$2.PartialStrykerOptions;

In 11.0.0, StrykerConfig as a type is the class instance { entries: Record<string, unknown> }, so a PartialStrykerOptions value no longer fits a StrykerConfig annotation.

Orientation

  • The change landed in refactor(repo): move every package to the compound-pack bar #94 (refactor(repo): move every package to the compound-pack bar), which moved the helpers onto the class in packages/stryker-js/src/config/stryker-config.schema.ts at ff66457. The 10.x helpers lived in src/config/define-config.ts and src/config/merge-config.ts; the entry point is src/config/mod.ts.
  • The changeset that describes the removal, .changeset/stryker-js-config-and-exports.md (major), is still unconsumed on main at ff66457. It also announces other removals (createDefaultOptions, SUPPORTED_CONFIG_FILE_NAMES, calculateMetrics, and others) that are out of scope here.
  • packages/stryker-js/README.md documents StrykerConfig.define / StrykerConfig.merge as the config API, as does the README of every package whose example uses them.
  • The package already runs typecheck (tsc -b), test (vitest run) and api:check (api-extractor run).

Non-Counting Outcomes

  • A CHANGELOG or migration note that documents the removal. The ask is to restore the ergonomic API; documenting the break keeps it broken.
  • Restoring defineConfig and mergeConfig as runtime exports while StrykerConfig remains the class, so the runtime import resolves but const config: StrykerConfig = defineConfig({…}) still fails to typecheck.
  • Restoring the exports in source while the pending changeset still ships, so the next CHANGELOG announces the removal of defineConfig / mergeConfig that the same release reverts.
  • A test that imports defineConfig from src/config/mod.ts only, while the built ./config entry point (dist/config.mjs / dist/config.d.mts) still lacks the export.
  • Restoring defineConfig with a narrower signature than 10.1.1: it must accept a plain object, a promise, and a (env: ConfigEnv) => … factory, as the four 10.1.1 overloads do.

Acceptance Criteria

  • pnpm --filter @systemfsoftware/stryker-js typecheck and test exit 0, including a check that fails on ff66457: a config module importing { defineConfig, mergeConfig, type StrykerConfig } from @systemfsoftware/stryker-js/config with const config: StrykerConfig = defineConfig({…}) and mergeConfig(base, overrides) typechecks and loads (gatekeeper).
  • The built dist/config.mjs exports defineConfig and mergeConfig as named exports, and dist/config.d.mts declares the four defineConfig overloads, mergeConfig(defaults, overrides), and StrykerConfig as the partial-options type (inspect pnpm --filter @systemfsoftware/stryker-js build output).
  • No unconsumed changeset on main announces the removal of defineConfig or mergeConfig; the release that restores them carries a CHANGELOG entry saying so.
  • packages/stryker-js/README.md and every package README that shows a Stryker config example use defineConfig / mergeConfig from ./config.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions