-
Notifications
You must be signed in to change notification settings - Fork 7
Add Fern Replay docs and migration guide #5497
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
tstanmay13
wants to merge
7
commits into
main
Choose a base branch
from
tanmay/replay-docs
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
ed7590a
Add Fern Replay docs and migration guide
tstanmay13 8d35d23
Address vale linter feedback
tstanmay13 7863582
Update Replay docs to GA messaging
tstanmay13 aed299f
make edits for structure and clarity
devalog 64c717c
Merge branch 'tanmay/replay-docs' of https://github.com/fern-api/docs…
devalog ca8f399
update lang-specific custom code pages
devalog 2e882dc
custom anchors
devalog File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -90,3 +90,4 @@ exceptions: | |
| - OG | ||
| - BCP | ||
| - ISO | ||
| - Replay | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,25 @@ | ||
| --- | ||
| title: Adding custom code | ||
| headline: Adding custom code (overview) | ||
| description: Extend Fern-generated SDKs with custom methods, logic, and dependencies. Use .fernignore to protect your code from being overwritten during regeneration. | ||
| description: Extend Fern-generated SDKs with custom methods, logic, and dependencies. Use Fern Replay for line-level edits and .fernignore for files you own end-to-end. | ||
| --- | ||
|
|
||
|
|
||
| Fern-generated SDKs are designed to be extended with custom logic, methods, and dependencies. If you want your SDK to do more than just make basic API calls (like combining multiple calls, processing data, adding utilities), you can add custom code that lives in harmony with the generated code. | ||
|
|
||
| You can also add custom methods by inheriting the Fern generated client and extending it, plus add any dependencies that your custom methods depend on in your `generators.yml` file. | ||
| Fern provides two complementary tools for keeping your customizations safe across regenerations: | ||
|
|
||
| ## Using `.fernignore` to preserve your customizations | ||
| - **`.fernignore`** — Full-file ownership. The generator stops touching listed files entirely. Use for fully hand-written modules, READMEs, or custom workflows. Trade-off: you also stop receiving generator updates to those files. | ||
| - **Replay** — Line-level edits. Keep generated files under generator control, and reapply your edits via 3-way merge on every regeneration. | ||
|
|
||
| Once you add files containing custom code, use `.fernignore` to protect your custom code from being overwritten when Fern regenerates your SDK. | ||
|
|
||
| Simply add your custom files to the SDK repository and list them in `.fernignore`. Fern won't override any files listed there. A `.fernignore` file is automatically created in your SDK repository when you use GitHub publishing. | ||
| ## Full-file ownership with `.fernignore` [#fernignore] | ||
|
|
||
| <Note>`.fernignore` applies only to SDK generation. It has no effect on [Fern Docs](/learn/docs/getting-started/overview) builds.</Note> | ||
|
|
||
| Use `.fernignore` to protect files you own end-to-end from being overwritten during SDK regeneration. | ||
|
|
||
| Add your custom files to the SDK repository and list them in `.fernignore`. A `.fernignore` file is automatically created in your SDK repository when you use GitHub publishing. | ||
|
|
||
| Your `.fernignore` file might look something like this: | ||
|
|
||
| ```gitignore title=".fernignore" | ||
|
|
@@ -31,7 +34,8 @@ LICENSE | |
| # Custom code | ||
| src/CustomClient.ts | ||
| ``` | ||
| <Note>For another example, see Cohere's [`.fernignore` file for their TypeScript SDK](https://github.com/cohere-ai/cohere-typescript/blob/ad583e3003bd51e80a82317f9e16beec85881b86/.fernignore).</Note> | ||
|
|
||
| For another real-world example, see Cohere's [`.fernignore` file for their TypeScript SDK](https://github.com/cohere-ai/cohere-typescript/blob/ad583e3003bd51e80a82317f9e16beec85881b86/.fernignore). | ||
|
|
||
| You'll have a separate `.fernignore` file for each of your SDKs: | ||
|
|
||
|
|
@@ -61,24 +65,39 @@ You'll have a separate `.fernignore` file for each of your SDKs: | |
| </Folder> | ||
| </Files> | ||
|
|
||
| ## Line-level edits with Replay [#replay] | ||
|
|
||
| <Note title="Requirements"> | ||
| Replay is on by default for SDKs using [`pull-request` output mode](/learn/sdks/reference/generators-yml#pull-request). To enable Replay on an SDK that's currently on `release` or `push` mode, switch to `pull-request` mode via the [migration guide](/learn/sdks/overview/replay-migration). | ||
|
|
||
| Replay requires the latest Fern CLI and SDK generator versions — run `fern upgrade` to make sure you're current. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| </Note> | ||
|
|
||
| Replay automatically preserves the edits you make to your generated SDK across regenerations. When you commit a change to generated code, Replay scans your repo's history since the last `[fern-generated]` commit and stores each customer commit as a tracked patch in `.fern/replay.lock`. On the next `fern generate`, those patches are reapplied to the freshly generated SDK via 3-way merge, and the result lands as a `[fern-replay]` commit on top of `[fern-generated]` in the regeneration PR: | ||
|
|
||
| ```text title="Regeneration PR" | ||
| * abc123 (HEAD -> main) [fern-replay] Apply customizations | ||
| * 789abc [fern-generated] Update SDK to spec rev 0451 | ||
| * 234bcd Add helpers on top of User type | ||
| * ... | ||
| ``` | ||
|
|
||
| If the generator and your customization changed the same lines, Replay reports the conflict in the PR body. Run [`fern replay resolve`](/learn/cli-api-reference/cli-reference/commands#fern-replay-resolve) locally to walk through it. | ||
|
|
||
| ### Disable Replay | ||
|
|
||
| To disable Replay for a specific generator, set `replay.enabled: false` in `generators.yml`. See the [`replay` reference](/learn/sdks/reference/generators-yml#replay) for global and per-generator configuration. | ||
|
|
||
| ## Customization patterns by language | ||
|
|
||
| Each SDK generator has its own conventions for adding custom code: how to extend the generated client, where helpers go, how to declare dependencies. See the guide for your language: | ||
|
|
||
| ## Augmenting your SDK with custom code | ||
|
|
||
| Get started adding custom code to a specific SDK: | ||
|
|
||
| <CardGroup cols={3}> | ||
| <Card title="TypeScript" icon={<img src="./images/icons/ts-light.svg" alt="TypeScript logo" className="h-6 w-6" noZoom />} href="/sdks/generators/typescript/custom-code"> | ||
| </Card> | ||
| <Card title="Python" icon={<img src="./images/icons/python-light.svg" className="h-6 w-6" noZoom />} href="/sdks/generators/python/custom-code"> | ||
| </Card> | ||
| <Card title="Go" icon={<img src="./images/icons/go-light.svg" className="h-6 w-6" noZoom />} href="/learn/sdks/generators/go/custom-code"> | ||
| </Card> | ||
| <Card title="Java" icon={<img src="./images/icons/java-light.svg" className="h-6 w-6" noZoom />} href="/learn/sdks/generators/java/custom-code"> | ||
| </Card> | ||
| <Card title=".NET" icon={<img src="./images/icons/csharp-light.svg" className="h-6 w-6" noZoom />} href="/sdks/generators/csharp/custom-code"> | ||
| </Card> | ||
| <Card title="PHP" icon={<img src="./images/icons/php-light.svg" className="h-6 w-6" noZoom />} href="/sdks/generators/php/custom-code"> | ||
| </Card> | ||
| <Card title="Ruby" icon={<img src="./images/icons/ruby-light.svg" className="h-6 w-6" noZoom />} href="/sdks/generators/ruby/custom-code"> | ||
| </Card> | ||
| </CardGroup> | ||
| <CardGroup cols={4}> | ||
| <Card title="TypeScript" icon={<img src="./images/icons/ts-light.svg" alt="TypeScript logo" className="h-6 w-6" noZoom />} href="/sdks/generators/typescript/custom-code" /> | ||
| <Card title="Python" icon={<img src="./images/icons/python-light.svg" className="h-6 w-6" noZoom />} href="/sdks/generators/python/custom-code" /> | ||
| <Card title="Go" icon={<img src="./images/icons/go-light.svg" className="h-6 w-6" noZoom />} href="/learn/sdks/generators/go/custom-code" /> | ||
| <Card title="Java" icon={<img src="./images/icons/java-light.svg" className="h-6 w-6" noZoom />} href="/learn/sdks/generators/java/custom-code" /> | ||
| <Card title=".NET" icon={<img src="./images/icons/csharp-light.svg" className="h-6 w-6" noZoom />} href="/sdks/generators/csharp/custom-code" /> | ||
| <Card title="PHP" icon={<img src="./images/icons/php-light.svg" className="h-6 w-6" noZoom />} href="/sdks/generators/php/custom-code" /> | ||
| <Card title="Ruby" icon={<img src="./images/icons/ruby-light.svg" className="h-6 w-6" noZoom />} href="/sdks/generators/ruby/custom-code" /> | ||
| </CardGroup> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[FernStyles.Current] Avoid time-relative terms like 'currently' that become outdated