Skip to content

Commit 9b1e4ae

Browse files
Upgrade Fern generator (#249)
This change is the result of re-generating the SDK using the latest v3 Fern generator (`3.27.6`) and re-applying the `BaseClient` builder fixes. --------- Co-authored-by: fern-api[bot] <115122769+fern-api[bot]@users.noreply.github.com> Co-authored-by: Jay Vercellone <jay.vercellone@workday.com>
1 parent e0c042c commit 9b1e4ae

96 files changed

Lines changed: 2095 additions & 770 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.fern/metadata.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"cliVersion": "3.5.0",
3+
"generatorName": "fernapi/fern-java-sdk",
4+
"generatorVersion": "3.27.6",
5+
"generatorConfig": {
6+
"publish-to": "central",
7+
"client-class-name": "BaseClient",
8+
"custom-dependencies": [
9+
"api org.apache.commons:commons-text:1.13.1"
10+
]
11+
},
12+
"sdkVersion": "1.2.0"
13+
}

.fernignore

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ LICENSE
1010
reference.md
1111

1212
# Base client files (temporary)
13-
# src/main/java/com/pipedream/api/AsyncBaseClientBuilder.java
14-
# src/main/java/com/pipedream/api/BaseClientBuilder.java
13+
src/main/java/com/pipedream/api/AsyncBaseClientBuilder.java
14+
src/main/java/com/pipedream/api/BaseClientBuilder.java
1515

1616
# Custom Pipedream client files
1717
src/main/java/com/pipedream/api/AsyncPipedreamClient.java
@@ -45,3 +45,8 @@ src/main/java/com/pipedream/api/types/HTTPAuthType.java
4545
src/test/java/com/pipedream/api/OauthTokensWireTest.java
4646
src/test/java/com/pipedream/api/ProxyClientWireTest.java
4747
src/test/java/com/pipedream/api/TokensWireTest.java
48+
49+
# Test utilities (JDK-only mock-server shim used by wire tests)
50+
src/test/java/com/pipedream/api/testutil/MockResponse.java
51+
src/test/java/com/pipedream/api/testutil/MockWebServer.java
52+
src/test/java/com/pipedream/api/testutil/RecordedRequest.java

CLAUDE.md

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# CLAUDE.md
2+
3+
Guidance for working in this repo with Claude Code (or any agent).
4+
5+
## What this repo is
6+
7+
Official Pipedream Java SDK. Most of the source tree is generated by **Fern**
8+
(generator: `fernapi/fern-java-sdk`, version pinned in `.fern/metadata.json`). A
9+
small set of files are hand-maintained on top of the generated code; they are
10+
listed explicitly in `.fernignore` and are the only files Fern won't overwrite
11+
on regeneration.
12+
13+
## The single most important rule
14+
15+
**If a file is not in `.fernignore`, do not edit it.** Fern owns it and the next
16+
regeneration will discard your changes. This includes:
17+
18+
- `build.gradle`, `settings.gradle`, `gradle/**`
19+
- The entire `.fern/` directory (incl. `.fern/metadata.json`)
20+
- `README.md`
21+
- Every file under `src/main/java/com/pipedream/api/` and
22+
`src/test/java/com/pipedream/api/` not in `.fernignore`
23+
24+
If you need to change something in a generated file, the change has to happen
25+
**upstream of this repo** — in the Fern API definition / generator config the
26+
bot reads from — and arrive here via the next regeneration. Locally, your
27+
options are: add the file to `.fernignore` (and own it going forward), or absorb
28+
the change into a hand-maintained wrapper. When in doubt, ask.
29+
30+
## What's hand-maintained
31+
32+
`.fernignore` is the source of truth. As of this writing:
33+
34+
| Path | Purpose |
35+
| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
36+
| `src/main/java/com/pipedream/api/PipedreamClient.java` | Public sync entry point. Wraps generated `BaseClient`, adds `workflows()` and `rawAccessToken()`, exposes the env-var-aware `builder()` factory. |
37+
| `src/main/java/com/pipedream/api/PipedreamClientBuilder.java` | Backward-compatible builder. Owns the `clientId/clientSecret/token/scope` fluent surface and orchestrates OAuth (`OAuthTokenSupplier`) or token-header auth in `build()`. |
38+
| `src/main/java/com/pipedream/api/AsyncPipedreamClient.java`, `AsyncPipedreamClientBuilder.java` | Async mirrors of the above. |
39+
| `src/main/java/com/pipedream/api/BaseClientBuilder.java`, `AsyncBaseClientBuilder.java` | Re-protected after the 3.27.6 regen so the generic `<T extends ...<T>>` self-type the Pipedream subclasses depend on cannot silently disappear in a future regen. |
40+
| `src/main/java/com/pipedream/api/resources/proxy/**` | Custom HTTP proxy implementation (request types, sync/async clients, `ProxyResponse`). |
41+
| `src/main/java/com/pipedream/api/resources/workflows/**`, `types/HTTPAuthType.java` | Custom workflow invocation surface. |
42+
| `src/test/java/com/pipedream/api/OauthTokensWireTest.java`, `ProxyClientWireTest.java`, `TokensWireTest.java` | Wire tests we own. |
43+
| `src/test/java/com/pipedream/api/testutil/MockWebServer.java`, `MockResponse.java`, `RecordedRequest.java` | JDK `HttpServer`-based mock-server shim. Replaces `okhttp3.mockwebserver` so we don't need to thread an extra test dep through the Fern-managed `build.gradle`. |
44+
| `reference.md`, `LICENSE`, `.github/workflows/auto-close-empty-prs.yml` | Docs / legal / CI we control. |
45+
46+
If you add a new hand-maintained file, list it in `.fernignore` in the same
47+
commit.
48+
49+
## Adding dependencies
50+
51+
`build.gradle` and `.fern/metadata.json` (where the `custom-dependencies` array
52+
lives) are both Fern-managed — neither can be edited in this repo. Adding a
53+
runtime or test dependency means changing the upstream Fern config and waiting
54+
for the next regen.
55+
56+
**If you need the dep in this repo before then, do not "bridge" by editing
57+
`build.gradle` — find another path.** For test-only dependencies, prefer the JDK
58+
or write a shim in `src/test/java/com/pipedream/api/testutil/` (already
59+
`.fernignore`-protected). The existing `MockWebServer` shim is the worked
60+
example: it sidesteps `okhttp3.mockwebserver` so we don't need a test dep at
61+
all.
62+
63+
## Versioning
64+
65+
The version is propagated by Fern from upstream config into `build.gradle` and
66+
`.fern/metadata.json`'s `sdkVersion`. Don't bump it in either place locally —
67+
the bump has to happen upstream and ride in via regen.
68+
69+
This SDK currently follows the convention: any net-new public API surface is a
70+
**minor bump** (no breaking change), any removal/rename is a **major bump**.
71+
Backward compatibility for the `PipedreamClient.builder()` chain is a hard
72+
requirement — see the next section.
73+
74+
## Public API contract (PipedreamClient)
75+
76+
The supported customer-facing API on the sync side (mirror exists on async):
77+
78+
```java
79+
// Env-aware: reads PIPEDREAM_CLIENT_ID, _CLIENT_SECRET, _BASE_URL,
80+
// _PROJECT_ENVIRONMENT, _PROJECT_ID
81+
PipedreamClient.builder()
82+
.clientId("...") // override env default
83+
.clientSecret("...") // override env default
84+
.scope("read:accounts") // OAuth progressive scopes (added 1.2.0)
85+
.token("eyJ...") // bypass OAuth entirely; precedence over creds
86+
.url("https://...") // alias: baseUrl(...)
87+
.projectId("...")
88+
.projectEnvironment("...")
89+
.timeout(60).maxRetries(2)
90+
.httpClient(myOkHttpClient)
91+
.addHeader("X-Foo", "bar")
92+
.build();
93+
```
94+
95+
Build-time precedence in `PipedreamClientBuilder.build()`:
96+
97+
1. `token != null``Authorization: Bearer <token>`
98+
2. else `clientId != null && clientSecret != null` → OAuth client-credentials
99+
via `OAuthTokenSupplier` + `OauthTokensClient` (lazy on first request)
100+
3. else → no auth header
101+
102+
`.clientId(null) / .clientSecret(null)` is a supported way to suppress the
103+
env-var defaults for tests.
104+
105+
## Why we don't add `withCredentials`/`withToken` to PipedreamClient
106+
107+
The generated `BaseClient` exposes `static withCredentials(...)` and `static
108+
withToken(...)` returning `BaseClientBuilder._CredentialsAuth` and `_TokenAuth`.
109+
Java's static-method-hiding rules require any same-name static on a subclass to
110+
have a covariant return type. `PipedreamClientBuilder` is not a subtype of
111+
`_CredentialsAuth` / `_TokenAuth`, so adding those statics on `PipedreamClient`
112+
won't compile. The hybrid surface above (env-aware `builder()` plus
113+
`.token(...)` and `.scope(...)`) is the workaround.
114+
115+
Customers wanting the Fern-native factory style can still call
116+
`BaseClient.withCredentials(...)` / `BaseClient.withToken(...)` directly — they
117+
just lose the `workflows()` accessor.
118+
119+
## Testing
120+
121+
```bash
122+
./gradlew test # full unit + wire suite (28 tests as of 1.2.0)
123+
./gradlew compileJava # main sources only
124+
./gradlew clean test # forces re-run; useful when fiddling with test code
125+
```
126+
127+
Wire tests use the `com.pipedream.api.testutil` shim — `MockWebServer` is backed
128+
by `com.sun.net.httpserver.HttpServer`, no external dep. The shim only
129+
implements the surface the tests use (`start`, `shutdown`, `url`, `enqueue`,
130+
`takeRequest`, plus `MockResponse` setters and `RecordedRequest` getters).
131+
Extend it if a test needs more.
132+
133+
When writing a wire test, prefer constructing the client via
134+
`PipedreamClient.builder().url(server.url("/").toString()).build()` over `new
135+
PipedreamClientBuilder()` — it's the public factory and matches how customers
136+
wire things up. Heads up: `builder()` reads `PIPEDREAM_CLIENT_ID` /
137+
`PIPEDREAM_CLIENT_SECRET` from the environment, so if those are set on the
138+
machine the OAuth flow will fire on the first request and consume an extra
139+
queued response. CI is clean; locally, unset them or pass explicit
140+
`.clientId(null).clientSecret(null)`.
141+
142+
`./gradlew spotlessCheck` is **broken** on newer JDKs (Palantir Java Format
143+
calls `JCImport.getQualifiedIdentifier()` which the JDK has removed). It was
144+
broken before the recent regen too. Don't try to "fix" it as part of an
145+
unrelated change — it's a separate cleanup that needs the spotless / PJF plugin
146+
versions bumped, and those live in the Fern-generated `build.gradle`.
147+
148+
## Java compatibility
149+
150+
`sourceCompatibility` / `targetCompatibility` are pinned at Java 8. Keep new
151+
hand-written code Java-8-compatible: no `var`, no `record`, no `List.of`, no
152+
`InputStream.readAllBytes()` (see the helper in `ProxyClientWireTest`).
153+
154+
## After a Fern regen
155+
156+
When a Fern bot PR lands, expect:
157+
158+
1. `build.gradle` to change (deps, version, sometimes plugins).
159+
2. `README.md` to be regenerated wholesale.
160+
3. Generated source under `src/main/java/com/pipedream/api/` to churn.
161+
4. The files in `.fernignore` to stay untouched.
162+
163+
Sanity checks before merging a regen PR:
164+
165+
- `./gradlew compileJava` is green.
166+
- `./gradlew test` is green.
167+
- The public API on `PipedreamClient` / `AsyncPipedreamClient` (see contract
168+
section above) still compiles. Inspect any change to `BaseClient` /
169+
`AsyncBaseClient` static factories carefully — those are what the wrappers
170+
build on top of.
171+
- The dep set in the regenerated `build.gradle` still has everything the wire
172+
tests need (today: nothing beyond what Fern emits, since the `testutil/` shim
173+
removed the `okhttp3.mockwebserver` requirement).
174+
175+
## Don't
176+
177+
- Don't edit `build.gradle` or `.fern/metadata.json` to add deps, change
178+
versions, or touch plugins/config. Both are Fern-managed; the change has to
179+
happen upstream.
180+
- Don't edit `README.md`. It's regenerated. Put project-specific docs in
181+
`reference.md` (which is in `.fernignore`).
182+
- Don't add backward-compatibility shims that mutate generated code. If the
183+
generated API changed in a way that breaks customers, absorb the change in the
184+
hand-maintained wrappers (`PipedreamClient*`) — that's what they exist for.
185+
- Don't introduce new test dependencies via `build.gradle`. Use the JDK or
186+
extend `testutil/`.
187+
- Don't try to add `static withCredentials(...)` / `static withToken(...)` on
188+
`PipedreamClient` — it won't compile (see the rationale section above).

README.md

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Add the dependency in your `build.gradle` file:
2828

2929
```groovy
3030
dependencies {
31-
implementation 'com.pipedream:pipedream:1.1.14'
31+
implementation 'com.pipedream:pipedream'
3232
}
3333
```
3434

@@ -40,7 +40,7 @@ Add the dependency in your `pom.xml` file:
4040
<dependency>
4141
<groupId>com.pipedream</groupId>
4242
<artifactId>pipedream</artifactId>
43-
<version>1.1.14</version>
43+
<version>1.2.0</version>
4444
</dependency>
4545
```
4646

@@ -56,12 +56,10 @@ import com.pipedream.api.resources.actions.requests.RunActionOpts;
5656

5757
public class Example {
5858
public static void main(String[] args) {
59-
BaseClient client = BaseClient
60-
.builder()
61-
.clientId("<clientId>")
62-
.clientSecret("<clientSecret>")
59+
BaseClient client = BaseClient.withCredentials("<clientId>", "<clientSecret>")
6360
.projectId("YOUR_PROJECT_ID")
64-
.build();
61+
.build()
62+
;
6563

6664
client.actions().run(
6765
RunActionOpts
@@ -73,6 +71,29 @@ public class Example {
7371
}
7472
}
7573
```
74+
## Authentication
75+
76+
This SDK supports two authentication methods:
77+
78+
### Option 1: Direct Bearer Token
79+
80+
If you already have a valid access token, you can use it directly:
81+
82+
```java
83+
BaseClient client = BaseClient.withToken("your-access-token")
84+
.url("https://api.example.com")
85+
.build();
86+
```
87+
88+
### Option 2: OAuth Client Credentials
89+
90+
The SDK can automatically handle token acquisition and refresh:
91+
92+
```java
93+
BaseClient client = BaseClient.withCredentials("client-id", "client-secret")
94+
.url("https://api.example.com")
95+
.build();
96+
```
7697

7798
## Environments
7899

@@ -119,7 +140,7 @@ try{
119140

120141
### Custom Client
121142

122-
This SDK is built to work with any instance of `OkHttpClient`. By default, if no client is provided, the SDK will construct one.
143+
This SDK is built to work with any instance of `OkHttpClient`. By default, if no client is provided, the SDK will construct one.
123144
However, you can pass your own client like so:
124145

125146
```java
@@ -138,7 +159,9 @@ BaseClient client = BaseClient
138159

139160
The SDK is instrumented with automatic retries with exponential backoff. A request will be retried as long
140161
as the request is deemed retryable and the number of retry attempts has not grown larger than the configured
141-
retry limit (default: 2).
162+
retry limit (default: 2). Before defaulting to exponential backoff, the SDK will first attempt to respect
163+
the `Retry-After` header (as either in seconds or as an HTTP date), and then the `X-RateLimit-Reset` header
164+
(as a Unix timestamp in epoch seconds); failing both of those, it will fall back to exponential backoff.
142165

143166
A request is deemed retryable when any of the following HTTP status codes is returned:
144167

@@ -160,23 +183,22 @@ BaseClient client = BaseClient
160183
### Timeouts
161184

162185
The SDK defaults to a 60 second timeout. You can configure this with a timeout option at the client or request level.
163-
164186
```java
165187
import com.pipedream.api.BaseClient;
166188
import com.pipedream.api.core.RequestOptions;
167189

168190
// Client level
169191
BaseClient client = BaseClient
170192
.builder()
171-
.timeout(10)
193+
.timeout(60)
172194
.build();
173195

174196
// Request level
175197
client.actions().run(
176198
...,
177199
RequestOptions
178200
.builder()
179-
.timeout(10)
201+
.timeout(60)
180202
.build()
181203
);
182204
```
@@ -207,6 +229,19 @@ client.actions().run(
207229
);
208230
```
209231

232+
### Access Raw Response Data
233+
234+
The SDK provides access to raw response data, including headers, through the `withRawResponse()` method.
235+
The `withRawResponse()` method returns a raw client that wraps all responses with `body()` and `headers()` methods.
236+
(A normal client's `response` is identical to a raw client's `response.body()`.)
237+
238+
```java
239+
RunHttpResponse response = client.actions().withRawResponse().run(...);
240+
241+
System.out.println(response.body());
242+
System.out.println(response.headers().get("X-My-Header"));
243+
```
244+
210245
## Contributing
211246

212247
While we value open-source contributions to this SDK, this library is generated programmatically.

build.gradle

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,14 @@ repositories {
1414
}
1515

1616
dependencies {
17-
api 'com.squareup.okhttp3:okhttp:4.12.0'
18-
api 'com.fasterxml.jackson.core:jackson-databind:2.17.2'
19-
api 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.2'
20-
api 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2'
17+
api 'com.squareup.okhttp3:okhttp:5.2.1'
18+
api 'com.fasterxml.jackson.core:jackson-databind:2.18.2'
19+
api 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.2'
20+
api 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2'
2121
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
2222
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
2323
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.2'
2424
api 'org.apache.commons:commons-text:1.13.1'
25-
testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0'
2625
}
2726

2827

@@ -49,7 +48,7 @@ java {
4948

5049
group = 'com.pipedream'
5150

52-
version = '1.1.14'
51+
version = '1.2.0'
5352

5453
jar {
5554
dependsOn(":generatePomFileForMavenPublication")
@@ -80,7 +79,7 @@ publishing {
8079
maven(MavenPublication) {
8180
groupId = 'com.pipedream'
8281
artifactId = 'pipedream'
83-
version = '1.1.14'
82+
version = '1.2.0'
8483
from components.java
8584
pom {
8685
name = 'pipedream'

0 commit comments

Comments
 (0)