From 898c51f85557c0d1ce914f43ef3e256e99a7c20e Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 16:41:02 +0000 Subject: [PATCH] SDK regeneration --- package.json | 1 - src/management/api/types/types.ts | 9 -- src/management/core/fetcher/Fetcher.ts | 1 + src/management/core/fetcher/makeRequest.ts | 28 +++++ src/management/core/runtime/runtime.ts | 16 +-- .../tests/mock-server/mockEndpointBuilder.ts | 10 +- .../tests/mock-server/withFormUrlEncoded.ts | 19 +++- .../tests/unit/fetcher/makeRequest.test.ts | 106 +++++++++++++++++- 8 files changed, 164 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 3278fc77bd..ef3485e695 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "types": "./dist/cjs/index.d.ts", "exports": { ".": { - "types": "./dist/cjs/index.d.ts", "import": { "types": "./dist/esm/index.d.mts", "default": "./dist/esm/index.mjs" diff --git a/src/management/api/types/types.ts b/src/management/api/types/types.ts index 59293979f2..82ea313bfa 100644 --- a/src/management/api/types/types.ts +++ b/src/management/api/types/types.ts @@ -3421,14 +3421,6 @@ export type ConnectionDomainGoogleApps = string; */ export type ConnectionDomainOkta = string; -/** Algorithm used for DPoP proof JWT signing. */ -export const ConnectionDpopSigningAlgEnum = { - Es256: "ES256", - Ed25519: "Ed25519", -} as const; -export type ConnectionDpopSigningAlgEnum = - (typeof ConnectionDpopSigningAlgEnum)[keyof typeof ConnectionDpopSigningAlgEnum]; - /** * JSON array containing a list of the JWS signing algorithms (alg values) supported for DPoP proof JWT signing. */ @@ -4372,7 +4364,6 @@ export interface ConnectionOptionsCommonOidc { client_secret?: Management.ConnectionClientSecretOidc | undefined; connection_settings?: Management.ConnectionConnectionSettings | undefined; domain_aliases?: Management.ConnectionDomainAliases | undefined; - dpop_signing_alg?: Management.ConnectionDpopSigningAlgEnum | undefined; federated_connections_access_tokens?: (Management.ConnectionFederatedConnectionsAccessTokens | null) | undefined; icon_url?: Management.ConnectionIconUrl | undefined; id_token_signed_response_algs?: ((Management.ConnectionIdTokenSignedResponseAlgs | undefined) | null) | undefined; diff --git a/src/management/core/fetcher/Fetcher.ts b/src/management/core/fetcher/Fetcher.ts index 5e5058a914..764d2e195a 100644 --- a/src/management/core/fetcher/Fetcher.ts +++ b/src/management/core/fetcher/Fetcher.ts @@ -282,6 +282,7 @@ export async function fetcherImpl(args: Fetcher.Args): Promise Promise, url: string, @@ -10,6 +36,7 @@ export const makeRequest = async ( abortSignal?: AbortSignal, withCredentials?: boolean, duplex?: "half", + disableCache?: boolean, ): Promise => { const signals: AbortSignal[] = []; @@ -32,6 +59,7 @@ export const makeRequest = async ( credentials: withCredentials ? "include" : undefined, // @ts-ignore duplex, + ...(disableCache && isCacheNoStoreSupported() ? { cache: "no-store" as RequestCache } : {}), }); if (timeoutAbortId != null) { diff --git a/src/management/core/runtime/runtime.ts b/src/management/core/runtime/runtime.ts index 56ebbb87c4..e6e66b2a7b 100644 --- a/src/management/core/runtime/runtime.ts +++ b/src/management/core/runtime/runtime.ts @@ -113,18 +113,18 @@ function evaluateRuntime(): Runtime { /** * A constant that indicates whether the environment the code is running is Node.JS. + * + * We assign `process` to a local variable first to avoid being flagged by + * bundlers that perform static analysis on `process.versions` (e.g. Next.js + * Edge Runtime warns about Node.js APIs even when they are guarded). */ - const isNode = - typeof process !== "undefined" && - "version" in process && - !!process.version && - "versions" in process && - !!process.versions?.node; + const _process = typeof process !== "undefined" ? process : undefined; + const isNode = typeof _process !== "undefined" && typeof _process.versions?.node === "string"; if (isNode) { return { type: "node", - version: process.versions.node, - parsedVersion: Number(process.versions.node.split(".")[0]), + version: _process.versions.node, + parsedVersion: Number(_process.versions.node.split(".")[0]), }; } diff --git a/src/management/tests/mock-server/mockEndpointBuilder.ts b/src/management/tests/mock-server/mockEndpointBuilder.ts index dc16c92e1a..d374a14040 100644 --- a/src/management/tests/mock-server/mockEndpointBuilder.ts +++ b/src/management/tests/mock-server/mockEndpointBuilder.ts @@ -2,9 +2,9 @@ import { type DefaultBodyType, type HttpHandler, HttpResponse, type HttpResponse import { url } from "../../core"; import { toJson } from "../../core/json"; -import { withFormUrlEncoded } from "./withFormUrlEncoded"; +import { type WithFormUrlEncodedOptions, withFormUrlEncoded } from "./withFormUrlEncoded"; import { withHeaders } from "./withHeaders"; -import { withJson, type WithJsonOptions } from "./withJson"; +import { type WithJsonOptions, withJson } from "./withJson"; type HttpMethod = "all" | "get" | "post" | "put" | "delete" | "patch" | "options" | "head"; @@ -27,7 +27,7 @@ interface RequestHeadersStage extends RequestBodyStage, ResponseStage { interface RequestBodyStage extends ResponseStage { jsonBody(body: unknown, options?: WithJsonOptions): ResponseStage; - formUrlEncodedBody(body: unknown): ResponseStage; + formUrlEncodedBody(body: unknown, options?: WithFormUrlEncodedOptions): ResponseStage; } interface ResponseStage { @@ -138,13 +138,13 @@ class RequestBuilder implements MethodStage, RequestHeadersStage, RequestBodySta return this; } - formUrlEncodedBody(body: unknown): ResponseStage { + formUrlEncodedBody(body: unknown, options?: WithFormUrlEncodedOptions): ResponseStage { if (body === undefined) { throw new Error( "Undefined is not valid for form-urlencoded. Do not call formUrlEncodedBody if you want an empty body.", ); } - this.predicates.push((resolver) => withFormUrlEncoded(body, resolver)); + this.predicates.push((resolver) => withFormUrlEncoded(body, resolver, options)); return this; } diff --git a/src/management/tests/mock-server/withFormUrlEncoded.ts b/src/management/tests/mock-server/withFormUrlEncoded.ts index dfae7e5062..a57a1df0a4 100644 --- a/src/management/tests/mock-server/withFormUrlEncoded.ts +++ b/src/management/tests/mock-server/withFormUrlEncoded.ts @@ -2,12 +2,26 @@ import { type HttpResponseResolver, passthrough } from "msw"; import { toJson } from "../../core/json"; +export interface WithFormUrlEncodedOptions { + /** + * List of field names to ignore when comparing request bodies. + * This is useful for pagination cursor fields that change between requests. + */ + ignoredFields?: string[]; +} + /** * Creates a request matcher that validates if the request form-urlencoded body exactly matches the expected object * @param expectedBody - The exact body object to match against * @param resolver - Response resolver to execute if body matches + * @param options - Optional configuration including fields to ignore */ -export function withFormUrlEncoded(expectedBody: unknown, resolver: HttpResponseResolver): HttpResponseResolver { +export function withFormUrlEncoded( + expectedBody: unknown, + resolver: HttpResponseResolver, + options?: WithFormUrlEncodedOptions, +): HttpResponseResolver { + const ignoredFields = options?.ignoredFields ?? []; return async (args) => { const { request } = args; @@ -41,7 +55,8 @@ export function withFormUrlEncoded(expectedBody: unknown, resolver: HttpResponse } const mismatches = findMismatches(actualBody, expectedBody); - if (Object.keys(mismatches).length > 0) { + const filteredMismatches = Object.keys(mismatches).filter((key) => !ignoredFields.includes(key)); + if (filteredMismatches.length > 0) { console.error("Form-urlencoded body mismatch:", toJson(mismatches, undefined, 2)); return passthrough(); } diff --git a/src/management/tests/unit/fetcher/makeRequest.test.ts b/src/management/tests/unit/fetcher/makeRequest.test.ts index 4d77a6c950..1ab1b39e57 100644 --- a/src/management/tests/unit/fetcher/makeRequest.test.ts +++ b/src/management/tests/unit/fetcher/makeRequest.test.ts @@ -1,4 +1,8 @@ -import { makeRequest } from "../../../../../src/management/core/fetcher/makeRequest"; +import { + makeRequest, + isCacheNoStoreSupported, + resetCacheNoStoreSupported, +} from "../../../src/management/core/fetcher/makeRequest"; describe("Test makeRequest", () => { const mockPostUrl = "https://httpbin.org/post"; @@ -11,6 +15,7 @@ describe("Test makeRequest", () => { beforeEach(() => { mockFetch = jest.fn(); mockFetch.mockResolvedValue(new Response(JSON.stringify({ test: "successful" }), { status: 200 })); + resetCacheNoStoreSupported(); }); it("should handle POST request correctly", async () => { @@ -50,4 +55,103 @@ describe("Test makeRequest", () => { expect(calledOptions.signal).toBeDefined(); expect(calledOptions.signal).toBeInstanceOf(AbortSignal); }); + + it("should not include cache option when disableCache is not set", async () => { + await makeRequest(mockFetch, mockGetUrl, "GET", mockHeaders, undefined); + const [, calledOptions] = mockFetch.mock.calls[0]; + expect(calledOptions.cache).toBeUndefined(); + }); + + it("should not include cache option when disableCache is false", async () => { + await makeRequest( + mockFetch, + mockGetUrl, + "GET", + mockHeaders, + undefined, + undefined, + undefined, + undefined, + undefined, + false, + ); + const [, calledOptions] = mockFetch.mock.calls[0]; + expect(calledOptions.cache).toBeUndefined(); + }); + + it("should include cache: no-store when disableCache is true and runtime supports it", async () => { + // In Node.js test environment, Request supports the cache option + expect(isCacheNoStoreSupported()).toBe(true); + await makeRequest( + mockFetch, + mockGetUrl, + "GET", + mockHeaders, + undefined, + undefined, + undefined, + undefined, + undefined, + true, + ); + const [, calledOptions] = mockFetch.mock.calls[0]; + expect(calledOptions.cache).toBe("no-store"); + }); + + it("should cache the result of isCacheNoStoreSupported", () => { + const first = isCacheNoStoreSupported(); + const second = isCacheNoStoreSupported(); + expect(first).toBe(second); + }); + + it("should reset cache detection state with resetCacheNoStoreSupported", () => { + // First call caches the result + const first = isCacheNoStoreSupported(); + expect(first).toBe(true); + + // Reset clears the cache + resetCacheNoStoreSupported(); + + // After reset, it should re-detect (and still return true in Node.js) + const second = isCacheNoStoreSupported(); + expect(second).toBe(true); + }); + + it("should not include cache option when runtime does not support it (e.g. Cloudflare Workers)", async () => { + // Mock Request constructor to throw when cache option is passed, + // simulating runtimes like Cloudflare Workers + const OriginalRequest = globalThis.Request; + globalThis.Request = class MockRequest { + constructor(_url: string, init?: RequestInit) { + if (init?.cache != null) { + throw new TypeError("The 'cache' field on 'RequestInitializerDict' is not implemented."); + } + } + } as unknown as typeof Request; + + try { + // Reset so the detection runs fresh with the mocked Request + resetCacheNoStoreSupported(); + expect(isCacheNoStoreSupported()).toBe(false); + + await makeRequest( + mockFetch, + mockGetUrl, + "GET", + mockHeaders, + undefined, + undefined, + undefined, + undefined, + undefined, + true, + ); + const [, calledOptions] = mockFetch.mock.calls[0]; + expect(calledOptions.cache).toBeUndefined(); + } finally { + // Restore original Request + globalThis.Request = OriginalRequest; + resetCacheNoStoreSupported(); + } + }); });