Skip to content

fix(mock): use exported element aliases for top-level array responses in arrayItems factories - #3709

Merged
melloware merged 4 commits into
orval-labs:masterfrom
the-ult:fix/3706-msw-unexported-item-aliases
Jul 12, 2026
Merged

fix(mock): use exported element aliases for top-level array responses in arrayItems factories#3709
melloware merged 4 commits into
orval-labs:masterfrom
the-ult:fix/3706-msw-unexported-item-aliases

Conversation

@the-ult

@the-ult the-ult commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #3706.

With mock.generators: [{ type: 'msw', arrayItems: true }], mocks for top-level array responses imported type names orval never emits — e.g. import type { GetCatalogItemsItemsItem } from './model' when only ItemsItem exists. The generated module then fails tsc as soon as it's exported from a library's public API (reproduced live at HEAD with three phantom shapes).

Root cause

getArrayItemFactoryNames (packages/mock/src/faker/getters/array-item-factory.ts) fabricates ${pascal(operationId)}${pascal(propertyName)}${itemSuffix} whenever parentName is undefined — i.e. whenever the array is the top-level response schema — instead of reusing the element alias the schema generator actually emits (<RefName><itemSuffix> for $ref'd arrays, the pre-[] alias for inline ones). The nested variant of this class was already fixed via the isAmbiguousInlineItemContext guard, confirming the intended contract: mock type names must equal schema-generator names.

Fix (pure bug fix, no config surface)

In the no-parentName branch only:

  • inline top-level array (Foo[] definition) → reuse the pre-[] alias, bailing out to the always-correct inline .map() body when the base isn't a plain identifier ((A | B)[], readonly X[]);
  • $ref'd array schema → reuse ${pascal(refName)}${itemSuffix} (same itemSuffix config core uses), bailing out for multi-ref allOf items with no direct properties (core emits no alias there);
  • factoryName formulas unchanged (outputs hitting this branch never compiled, so they're not a compat surface);
  • itemsRef branch, parentName branch, and ambiguity guard byte-identical.

Because every output that hit this branch failed tsc, no working project can observe a behavior change.

Verification

  • Unit: mock 302/302 ✓ (new failing-first tests for all branch shapes incl. bail-outs)
  • Snapshots: 5317/5317 ✓; 18 new snapshot files under tests/__snapshots__/mock/issue-3706-msw-array-item-aliases{,-strict}/**, zero modified existing snapshots (canaries faker-array-items, msw-array-items, issue-3590*, issue-3574* untouched)
  • New fixture reproduces the reporter's exact Get…ItemsItem phantom plus inline/nullable/parentName regression guards; the strict variant (override.mock.required/nonNullable) exercises ${typeName}Mock naming over the corrected aliases
  • All 16 generated clients typecheck (tests build gate) — the phantom import is exactly what this gate catches; lint clean

Follow-up (out of scope, discovered during research)

output.schemas: { type: 'zod' } barrels export no synthetic inline aliases at all (e.g. GetCatalogItemsInline200Item is imported by the plain fetch client itself yet missing from the zod model dir). That's a separate defect in the zod schema writer / import-rerouting path (packages/orval/src/write-specs.ts:294-330) affecting non-mock output too — it deserves its own issue rather than being folded in here; this PR's fix is correct independent of it. I can file that issue with a minimal repro if wanted.

Related issues

#3513 (reusable array-item mock factories — the feature this hardens), #3514 (arrayItems origin), #3269 / #3656 (same class: MSW missing imports), #3108 (zod + tags-split phantom exports), #3612 (faker import path), #3574 / #3590 (strict mock naming). Sibling cluster: #3702, #3704, #3705.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved mock generation for top-level array responses by producing correct reusable item factory names and imports.
    • Added safeguards for ambiguous array schemas to prevent incorrect factory generation.
  • Documentation
    • Updated the Faker guide to clarify how faker factories are derived for top-level array responses, including nullable and fallback/inlining behavior.
  • Tests
    • Expanded test coverage for referenced and inline top-level arrays, ambiguous/allOf cases, nullable arrays, and stricter item requirements.

… in arrayItems factories (orval-labs#3706)

getArrayItemFactoryNames fabricated `${pascal(operationId)}${pascal(propertyName)}Item`
for top-level array responses (no parentName), producing type names the schema
generator never emits — unexported/undeclared identifiers that fail tsc. Now the
mock generator derives the real emitted alias instead: for inline top-level arrays,
reuse the alias before the trailing `[]` (bailing on non-identifier bases like unions
or `readonly`); for `$ref`'d array schemas, reuse `<RefName><itemSuffix>` (bailing when
the items are a multi-ref `allOf` with no direct properties, since core emits no alias
there). All previously-working branches (itemsRef, parentName) are byte-identical.

Fixes orval-labs#3706

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 11, 2026 08:34
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b4155c1b-502c-4e73-879b-1884b8fe5f8a

📥 Commits

Reviewing files that changed from the base of the PR and between 708ea3a and 3f3bdcd.

⛔ Files ignored due to path filters (6)
  • tests/__snapshots__/mock/issue-3706-msw-array-item-aliases-strict/endpoints.ts is excluded by !**/__snapshots__/**
  • tests/__snapshots__/mock/issue-3706-msw-array-item-aliases-strict/model/getNullableCatalogItems200Item.ts is excluded by !**/__snapshots__/**
  • tests/__snapshots__/mock/issue-3706-msw-array-item-aliases-strict/model/index.ts is excluded by !**/__snapshots__/**
  • tests/__snapshots__/mock/issue-3706-msw-array-item-aliases/endpoints.ts is excluded by !**/__snapshots__/**
  • tests/__snapshots__/mock/issue-3706-msw-array-item-aliases/model/getNullableCatalogItems200Item.ts is excluded by !**/__snapshots__/**
  • tests/__snapshots__/mock/issue-3706-msw-array-item-aliases/model/index.ts is excluded by !**/__snapshots__/**
📒 Files selected for processing (3)
  • packages/mock/src/faker/getters/array-item-factory.test.ts
  • packages/mock/src/faker/getters/array-item-factory.ts
  • tests/specifications/issue-3706-msw-unexported-item-aliases.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/mock/src/faker/getters/array-item-factory.ts

📝 Walkthrough

Walkthrough

Top-level array faker factories now reuse derivable item aliases, reject ambiguous aliases, and add documentation, tests, OpenAPI fixtures, and MSW configurations covering referenced, inline, and nullable responses.

Changes

Top-level array item aliases

Layer / File(s) Summary
MSW regression fixtures
tests/specifications/issue-3706-msw-unexported-item-aliases.yaml, tests/configs/mock.config.ts
Adds referenced, inline, nullable, and composed array response scenarios with standard and strict MSW mock configurations.
Top-level alias inference and coverage
packages/mock/src/faker/getters/array-item-factory.ts, packages/mock/src/faker/getters/array-item-factory.test.ts, docs/content/docs/guides/faker.mdx
Derives top-level item aliases from array identifiers or item schemas, bails out for ambiguous shapes, and documents and tests emitted factories, imports, and nullable handling.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: mock

Suggested reviewers: wadakatu, melloware

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main fix: using exported element aliases for top-level array MSW factories.
Linked Issues check ✅ Passed The changes address #3706 by reusing exported collection/item aliases for top-level arrays, including nullable cases, with tests covering the fix.
Out of Scope Changes check ✅ Passed The added spec, configs, and tests all support the MSW array-item alias fix and do not introduce unrelated behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes MSW (arrayItems: true) mock generation for top-level array response schemas by aligning extracted array-item factory type names with the schema generator’s exported element aliases, preventing TypeScript compile failures from phantom/unexported imports (issue #3706).

Changes:

  • Updates array-item factory name/type derivation for top-level array responses, with conservative bail-outs when an alias can’t be derived reliably.
  • Adds a new repro specification + config targets and commits new snapshot fixtures (normal + strict mock modes).
  • Documents the top-level array response behavior in the Faker guide.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/specifications/issue-3706-msw-unexported-item-aliases.yaml Adds a repro OpenAPI spec covering top-level $ref and inline array responses plus a nested nullable-array guard.
tests/configs/mock.config.ts Adds two new mock generation targets for the new spec (normal + strict).
tests/snapshots/mock/issue-3706-msw-array-item-aliases/model/itemsItem.ts New snapshot: generated element alias for Items.
tests/snapshots/mock/issue-3706-msw-array-item-aliases/model/items.ts New snapshot: generated array alias Items = ItemsItem[].
tests/snapshots/mock/issue-3706-msw-array-item-aliases/model/index.ts New snapshot: barrel exports for the new fixture’s model types.
tests/snapshots/mock/issue-3706-msw-array-item-aliases/model/getNullableList200RowsItem.ts New snapshot: element alias for nested nullable array property.
tests/snapshots/mock/issue-3706-msw-array-item-aliases/model/getNullableList200.ts New snapshot: wrapper object with nullable array property typing.
tests/snapshots/mock/issue-3706-msw-array-item-aliases/model/getCatalogItemsInline200Item.ts New snapshot: emitted alias for inline top-level array element type.
tests/snapshots/mock/issue-3706-msw-array-item-aliases/model/catalogItemsItem.ts New snapshot: element alias for $ref’d array schema CatalogItems.
tests/snapshots/mock/issue-3706-msw-array-item-aliases/model/catalogItems.ts New snapshot: generated array alias CatalogItems = CatalogItemsItem[].
tests/snapshots/mock/issue-3706-msw-array-item-aliases/endpoints.ts New snapshot: MSW handlers + extracted array-item factories using exported element aliases.
tests/snapshots/mock/issue-3706-msw-array-item-aliases-strict/model/itemsItem.ts New snapshot: strict variant model output.
tests/snapshots/mock/issue-3706-msw-array-item-aliases-strict/model/items.ts New snapshot: strict variant array alias.
tests/snapshots/mock/issue-3706-msw-array-item-aliases-strict/model/index.ts New snapshot: strict variant barrel exports.
tests/snapshots/mock/issue-3706-msw-array-item-aliases-strict/model/getNullableList200RowsItem.ts New snapshot: strict variant element alias.
tests/snapshots/mock/issue-3706-msw-array-item-aliases-strict/model/getNullableList200.ts New snapshot: strict variant wrapper typing.
tests/snapshots/mock/issue-3706-msw-array-item-aliases-strict/model/getCatalogItemsInline200Item.ts New snapshot: strict variant inline element alias.
tests/snapshots/mock/issue-3706-msw-array-item-aliases-strict/model/catalogItemsItem.ts New snapshot: strict variant $ref array element alias.
tests/snapshots/mock/issue-3706-msw-array-item-aliases-strict/model/catalogItems.ts New snapshot: strict variant array alias.
tests/snapshots/mock/issue-3706-msw-array-item-aliases-strict/endpoints.ts New snapshot: strict variant MSW output + strict mock helper typings.
packages/mock/src/faker/getters/array-item-factory.ts Core fix: derives typeName from exported element aliases for top-level array responses; adds bail-outs for ambiguous expressions.
packages/mock/src/faker/getters/array-item-factory.test.ts Adds failing-first unit coverage for the fixed top-level array response cases and bail-out shapes.
docs/content/docs/guides/faker.mdx Documents how top-level array responses are handled (alias reuse + bail-outs).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +257 to +269
if (propertyName.endsWith('[]')) {
const base = propertyName.slice(0, -2);
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(base)) {
return undefined;
}
typeName = base;
} else {
const schema = items as OpenApiSchemaObject;
if (schema.allOf && !schema.properties && schema.type !== 'object') {
return undefined;
}
typeName = `${pascal(propertyName)}${itemSuffix}`;
}
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pkg-pr-new

pkg-pr-new Bot commented Jul 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

@orval/angular

bun add https://pkg.pr.new/@orval/angular@3f3bdcd

@orval/axios

bun add https://pkg.pr.new/@orval/axios@3f3bdcd

@orval/core

bun add https://pkg.pr.new/@orval/core@3f3bdcd

@orval/effect

bun add https://pkg.pr.new/@orval/effect@3f3bdcd

@orval/fetch

bun add https://pkg.pr.new/@orval/fetch@3f3bdcd

@orval/hono

bun add https://pkg.pr.new/@orval/hono@3f3bdcd

@orval/mcp

bun add https://pkg.pr.new/@orval/mcp@3f3bdcd

@orval/mock

bun add https://pkg.pr.new/@orval/mock@3f3bdcd

orval

bun add https://pkg.pr.new/orval@3f3bdcd

@orval/query

bun add https://pkg.pr.new/@orval/query@3f3bdcd

@orval/solid-start

bun add https://pkg.pr.new/@orval/solid-start@3f3bdcd

@orval/swr

bun add https://pkg.pr.new/@orval/swr@3f3bdcd

@orval/zod

bun add https://pkg.pr.new/@orval/zod@3f3bdcd

commit: 3f3bdcd

Copilot review: nullable top-level arrays reach the no-parentName branch
with a ' | null'-suffixed definition ('CatalogItems | null'), which fell
into the bare-ref-name path and fabricated phantom names. The suffix is
now stripped before branch selection, and the bare-name branch gained an
identifier guard that bails to the always-correct inline body for any
non-identifier shape. Fixture gains a nullable top-level array operation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@the-ult

the-ult commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

Copilot's nullable-array finding is fixed in fb4c14d: the ' | null' suffix is stripped before branch selection (so 'CatalogItems | null' resolves to the real CatalogItemsItem alias and 'Foo[] | null' to Foo), and the bare-name branch now has an identifier guard bailing to the inline item body for any non-identifier shape. The fixture gained a getNullableCatalogItems nullable top-level array operation — its generated snapshot imports only real, exported model types; unit tests cover all three nullable shapes.

@melloware melloware added the mock Related to mock generation label Jul 12, 2026
@melloware
melloware merged commit c1b4cf6 into orval-labs:master Jul 12, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mock Related to mock generation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(msw): Orval MSW unexported item aliases

3 participants