Skip to content

[pull] main from fern-api:main#772

Merged
pull[bot] merged 31 commits into
code:mainfrom
fern-api:main
Jun 5, 2026
Merged

[pull] main from fern-api:main#772
pull[bot] merged 31 commits into
code:mainfrom
fern-api:main

Conversation

@pull

@pull pull Bot commented Jun 5, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

jsklan and others added 30 commits June 5, 2026 13:56
)

* feat(cli-generator): generate reference.md for generated CLI

Adds automatic reference.md generation that documents all commands,
subcommands, flags, and HTTP mappings. Parses the mounted OpenAPI
spec(s) at generation time to derive the same resource→method command
tree that the Rust runtime builds. Also links the reference from the
generated README's Documentation section.

* fix: resolve biome lint errors (import order, non-null assertion)

* fix: include binaryName in TOC anchor links for correct navigation

* fix: escape pipe characters in description column to prevent table corruption

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…16288)

- Add Table of Contents generated after block merge
- Add Quick start section with minimal try-it examples
- Trim Usage section (remove --help dump, show subcommand pattern + --json)
- Move Documentation section before Advanced
- Collapse Common flags, Environment variables, Output formats, Shell completion into single Advanced H2 with ### subsections
- Update 24 seed snapshots
- Update unit tests for new section order and content

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…6289)

* fix(cli): fix datetime types compilation in types crate

Parameterize coreModulePath in the Rust model generator and copy core
serde helper modules into the CLI-generated types crate so that
#[serde(with = "crate::core::...")] attributes resolve at compile time.

- Add coreModulePath config option to BaseRustConfigSchema
- Add getCoreModulePath() to AbstractRustGeneratorContext
- Replace all hardcoded crate::core:: paths with dynamic paths in
  structUtils, UnionGenerator, UndiscriminatedUnionGenerator, AliasGenerator
- Copy flexible_datetime.rs, base64_bytes.rs, bigint_string.rs,
  number_serializers.rs into types crate src/core/
- Add chrono, base64, num-bigint, ordered-float deps to types crate
- Add chrono/ordered_float re-exports to types crate prelude
- Update Cargo.lock patching to include new deps

Closes FER-11024

* fix: add chrono/num-bigint/ordered-float to CLI SDK deps for Cargo.lock resolution

The types crate lists these as dependencies, but without [[package]]
entries in the shipped Cargo.lock, cargo build --locked would reject
the inconsistent lock file. Adding them to the SDK's own Cargo.toml
ensures they are resolved in the lock file naturally.

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…point responses (#16242)

* fix(java): generate standalone files for inline types only referenced from endpoint responses

When enable-inline-types is enabled, inline types that are only referenced
from endpoint response types (not from other type declarations) were skipped
during file generation. The generator assumed all inline types would be nested
inside parent types, but map value types in endpoint responses have no parent
type to nest into.

Added BFS reachability analysis from non-inline types to determine which inline
types will actually be nested. Only those are skipped; orphaned inline types are
now generated as standalone files.

Added test case to java-inline-types fixture with a map response endpoint.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* chore: apply spotless formatting

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* chore: update ir-to-jsonschema snapshot for MapResponseValue

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix: prevent duplicate standalone files for inline types nested inside orphaned inline types

Addresses Devin Review finding: when an orphaned inline type (only referenced
from endpoints) itself references other inline types, those child types should
be nested inside the orphan, not generated as redundant standalone files.

Added second pass in computeNestedInlineTypeIds() to mark inline types
referenced from orphaned inline types as nested. Also added test case with
MapResponseValueNested inside MapResponseValue to validate.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* chore: regenerate IR test definitions for java-inline-types

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(java): remove unsafe second-pass suppression of orphan-referenced inline types

The second pass unconditionally marked all inline types referenced by orphans
as nested, which fails for:
1. Self-referencing orphans (e.g. Tree { children: list<Tree> }) — the type
   appears in its own getReferencedTypes() (transitive closure) and gets
   suppressed with no parent to nest into.
2. Inline types shared between an orphan parent and an endpoint — the type
   gets suppressed but the endpoint client still emits a top-level import.

Fix: remove the second pass entirely. Orphan inline types that reference
other inline types will produce both a standalone file and a nested class
for the child — this duplication is harmless and always correct.

Also adds test fixtures for shared-inline-type (endpoint + orphan parent)
edge case.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test: add JSON schema snapshots for SharedChildType and OrphanParentWithSharedChild

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test: regenerate IR and dynamic-snippets test definitions for java-inline-types

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: cade <info@buildwithfern.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
)

* feat(cli-generator): always emit build+test CI workflow for GitHub outputs

Decouple CI workflow emission from npm publish config. When the output
mode is `github`, the generator now always emits a `ci.yml` with
check/compile/test jobs. Publish jobs are only appended when
npmPublishInfo is present.

- Add `isGithubOutput` field to `ResolvedOutputConfig`
- Add `emitCiWorkflow()` for build+test-only workflow
- Update `runPipeline` gating: `isGithubOutput` → CI, `npmPublishInfo` → publish
- Add tests for all new code paths

Resolves FER-11017

* feat(cli-generator): add github-no-publish seed fixture

Adds a new seed output folder for the query-parameters-openapi fixture
with github output mode but no npm publishConfig. Demonstrates that
the build+test-only ci.yml (check, compile, test — no publish jobs)
is emitted correctly.

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(rust): Add RequestExecutor trait for CLI execution-sharing

Add RequestExecutor trait and HttpClient::with_executor() constructor
to enable CLI execution-sharing. When an external executor is injected,
the SDK delegates HTTP execution entirely — auth, headers, and retries
are handled by the caller's transport stack.

Also adds cliEmbedded config flag that skips model generation when the
SDK is embedded in a CLI binary.

* fix(rust): Update http_client snapshot for RequestExecutor changes

* fix(rust): Address review findings - restore Clone, fix base64 executor, fix cliEmbedded types

- Restore #[derive(Clone)] on HttpClient (needed for pagination code gen)
- Update BASE64_METHOD template to use send_request() instead of direct
  apply_auth_headers/execute_with_retries (bypassed injected executor)
- Check cliEmbedded flag in generateApiModFile and generateLibFile to
  avoid declaring mod types when type generation is skipped

* fix(rust): Preserve SSE header precedence over custom headers

Move SSE-specific headers (Accept: text/event-stream, Cache-Control: no-store)
after apply_custom_headers in the default path so they always take precedence,
matching the original ordering. In the executor path, SSE headers are applied
before delegation.

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
A user property named EXTRA_PROPERTIES mapped to a GetExtraProperties() getter that collided with the built-in extra-properties accessor every generated object exposes, so the SDK did not compile (mixed-case fixture). Add 'extraproperties' to goReservedIdentifiers so such a property is generated as FieldExtraProperties (JSON wire name unchanged).
Co-authored-by: jsklan <100491078+jsklan@users.noreply.github.com>
* chore(seed): graduate imdb and exhaustive from cli allowedFailures

* chore(seed): restore exhaustive to cli allowedFailures, keep only imdb graduated

* chore(seed): update imdb cli seed output to match current generator

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jsklan <100491078+jsklan@users.noreply.github.com>
Add generateEmbeddedSdk step that invokes @fern-api/rust-sdk in
cliEmbedded mode to produce a <api>-sdk workspace member alongside
the existing <api>-types crate.

- New generateEmbeddedSdk.ts mirrors generateEmbeddedTypes pattern
- SDK crate declares path dep on types crate, re-exports via prelude
- New embedSdk config flag (default: true, requires embedTypes)
- patchCargoToml generalized with addCrateDependency + SDK lock patching
- patchDistWorkspace accepts sdkCrateName for workspace membership
- build.mjs bundles rust-sdk dist for Docker image
- custom.rs scaffold updated with SDK usage hints

Closes FER-11026

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(cli): ensure process exits after generation completes

Replace fire-and-forget `void generate()` with explicit
`process.exit(0)` on success / `process.exit(1)` on failure.
The previous pattern relied on the Node.js event loop draining
to exit, which hangs indefinitely when open handles (Sentry
timers, notification service intervals, child process stdio)
keep the loop alive.

* refactor(cli): use async IIFE instead of .then() chain

Per repo convention (CLAUDE.md / REVIEW.md): prefer async/await
over .then() chains.

* fix(cli): re-throw after error reporting so failures exit with code 1

The inner catch swallowed errors without re-throwing, causing
generate() to resolve normally on failure. The IIFE then called
process.exit(0) instead of process.exit(1).

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ifiers (#16290)

* fix(cli): map bedrock provider to aws-bedrock for BAML client registry

Co-Authored-By: rishabh <rishabh@buildwithfern.com>

* fix: add assertNever default case and core-utils dependency

Co-Authored-By: rishabh <rishabh@buildwithfern.com>

* break(cli): rename bedrock to aws-bedrock to match BAML provider identifiers

Co-Authored-By: rishabh <rishabh@buildwithfern.com>

* break(cli): rename bedrock to aws-bedrock in fernrc and cli-v2 AI config

Co-Authored-By: rishabh <rishabh@buildwithfern.com>

* chore: use feat type for changelog (break not supported by automation)

Co-Authored-By: rishabh <rishabh@buildwithfern.com>

* fix: add name property for aws-bedrock enum value

Co-Authored-By: rishabh <rishabh@buildwithfern.com>

* fix: restore pnpm-lock.yaml from main (no dependency changes)

Co-Authored-By: rishabh <rishabh@buildwithfern.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: rishabh <rishabh@buildwithfern.com>
…r specs (#16300)

build.rs generates smoke-test constants from customer-specific OpenAPI
specs (e.g. src/bin/box/openapi.yaml) that are correctly excluded by the
sync manifest. Since it panics when those files don't exist, remove it
from the vendored copy. The cli-sdk manifest has been updated to
classify build.rs as not-synced going forward.

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jsklan <100491078+jsklan@users.noreply.github.com>
…#16302)

feat(cli-generator): add changelog for cli-sdk sync with CliExecutor

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The sync-cli-sdk workflow vendors cli-sdk into generators/cli/sdk/ but
didn't create an unreleased changelog entry, so merging a sync PR never
triggered a new cli-generator Docker image publish.

Add a step that writes a chore changelog file keyed by the synced SHA,
and include the changelog path in the PR's add-paths so the release
automation picks it up after merge.

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…cy graph (#16304)

The cli-generator's build.mjs copies the rust-sdk dist/ into
dist/rust-sdk-dist/ for the Docker image, but the turbo.jsonc only
listed @fern-api/rust-model#dist:cli as a dependency. This meant the
rust-sdk dist was never built before the cli-generator's dist:cli ran,
causing the copy to silently fail (try/catch in build.mjs) and the
Docker image to ship without rust-sdk-dist/cli.cjs.

At runtime, generateEmbeddedSdk's resolveRustSdkCli() then throws
'Could not resolve the @fern-api/rust-sdk CLI' since neither the
bundled path nor the workspace resolution finds the entry point.

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@pull pull Bot locked and limited conversation to collaborators Jun 5, 2026
@pull pull Bot added the ⤵️ pull label Jun 5, 2026
@pull pull Bot merged commit 05e879c into code:main Jun 5, 2026
14 of 16 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants