@gbg/go-core 0.0.1-alpha.24 → 0.0.1-alpha.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/FUNCTIONS.md +1 -7
  2. package/README.md +14 -43
  3. package/dist/commonjs/funcs/tokens-generate.d.ts +2 -2
  4. package/dist/commonjs/funcs/tokens-generate.d.ts.map +1 -1
  5. package/dist/commonjs/funcs/tokens-generate.js +7 -9
  6. package/dist/commonjs/funcs/tokens-generate.js.map +1 -1
  7. package/dist/commonjs/hooks/registration.js +4 -4
  8. package/dist/commonjs/hooks/registration.js.map +1 -1
  9. package/dist/commonjs/hooks/types.d.ts +1 -0
  10. package/dist/commonjs/hooks/types.d.ts.map +1 -1
  11. package/dist/commonjs/hooks/x-gbg-source.d.ts +36 -0
  12. package/dist/commonjs/hooks/x-gbg-source.d.ts.map +1 -0
  13. package/dist/commonjs/hooks/x-gbg-source.js +41 -0
  14. package/dist/commonjs/hooks/x-gbg-source.js.map +1 -0
  15. package/dist/commonjs/lib/config.d.ts +3 -3
  16. package/dist/commonjs/lib/config.js +3 -3
  17. package/dist/commonjs/lib/encodings.js +12 -12
  18. package/dist/commonjs/lib/encodings.js.map +1 -1
  19. package/dist/commonjs/lib/env.d.ts.map +1 -1
  20. package/dist/commonjs/lib/env.js +3 -3
  21. package/dist/commonjs/lib/env.js.map +1 -1
  22. package/dist/commonjs/lib/matchers.js +3 -3
  23. package/dist/commonjs/lib/matchers.js.map +1 -1
  24. package/dist/commonjs/lib/primitives.d.ts +1 -0
  25. package/dist/commonjs/lib/primitives.d.ts.map +1 -1
  26. package/dist/commonjs/lib/primitives.js +18 -0
  27. package/dist/commonjs/lib/primitives.js.map +1 -1
  28. package/dist/commonjs/lib/retries.js +7 -0
  29. package/dist/commonjs/lib/retries.js.map +1 -1
  30. package/dist/commonjs/lib/sdks.d.ts.map +1 -1
  31. package/dist/commonjs/lib/sdks.js +50 -16
  32. package/dist/commonjs/lib/sdks.js.map +1 -1
  33. package/dist/commonjs/models/client-credentials-grant-request.d.ts +25 -0
  34. package/dist/commonjs/models/client-credentials-grant-request.d.ts.map +1 -0
  35. package/dist/commonjs/models/client-credentials-grant-request.js +58 -0
  36. package/dist/commonjs/models/client-credentials-grant-request.js.map +1 -0
  37. package/dist/commonjs/models/index.d.ts +2 -0
  38. package/dist/commonjs/models/index.d.ts.map +1 -1
  39. package/dist/commonjs/models/index.js +2 -0
  40. package/dist/commonjs/models/index.js.map +1 -1
  41. package/dist/commonjs/models/operations/fetch-interaction.d.ts +41 -12
  42. package/dist/commonjs/models/operations/fetch-interaction.d.ts.map +1 -1
  43. package/dist/commonjs/models/operations/fetch-interaction.js +45 -16
  44. package/dist/commonjs/models/operations/fetch-interaction.js.map +1 -1
  45. package/dist/commonjs/models/operations/index.d.ts +1 -1
  46. package/dist/commonjs/models/operations/index.d.ts.map +1 -1
  47. package/dist/commonjs/models/operations/index.js +1 -1
  48. package/dist/commonjs/models/operations/index.js.map +1 -1
  49. package/dist/commonjs/models/operations/post-as-token-oauth2.d.ts +32 -0
  50. package/dist/commonjs/models/operations/post-as-token-oauth2.d.ts.map +1 -0
  51. package/dist/commonjs/models/operations/{post-auth-realms-go-protocol-openid-connect-token.js → post-as-token-oauth2.js} +16 -35
  52. package/dist/commonjs/models/operations/post-as-token-oauth2.js.map +1 -0
  53. package/dist/commonjs/models/password-grant-request.d.ts +35 -0
  54. package/dist/commonjs/models/password-grant-request.d.ts.map +1 -0
  55. package/dist/commonjs/models/password-grant-request.js +60 -0
  56. package/dist/commonjs/models/password-grant-request.js.map +1 -0
  57. package/dist/commonjs/sdk/tokens.d.ts +2 -2
  58. package/dist/commonjs/sdk/tokens.d.ts.map +1 -1
  59. package/dist/commonjs/sdk/tokens.js +1 -1
  60. package/dist/commonjs/sdk/tokens.js.map +1 -1
  61. package/dist/esm/funcs/tokens-generate.d.ts +2 -2
  62. package/dist/esm/funcs/tokens-generate.d.ts.map +1 -1
  63. package/dist/esm/funcs/tokens-generate.js +7 -9
  64. package/dist/esm/funcs/tokens-generate.js.map +1 -1
  65. package/dist/esm/hooks/registration.js +4 -4
  66. package/dist/esm/hooks/registration.js.map +1 -1
  67. package/dist/esm/hooks/types.d.ts +1 -0
  68. package/dist/esm/hooks/types.d.ts.map +1 -1
  69. package/dist/esm/hooks/x-gbg-source.d.ts +36 -0
  70. package/dist/esm/hooks/x-gbg-source.d.ts.map +1 -0
  71. package/dist/esm/hooks/x-gbg-source.js +37 -0
  72. package/dist/esm/hooks/x-gbg-source.js.map +1 -0
  73. package/dist/esm/lib/config.d.ts +3 -3
  74. package/dist/esm/lib/config.js +3 -3
  75. package/dist/esm/lib/encodings.js +1 -1
  76. package/dist/esm/lib/encodings.js.map +1 -1
  77. package/dist/esm/lib/env.d.ts.map +1 -1
  78. package/dist/esm/lib/env.js +3 -3
  79. package/dist/esm/lib/env.js.map +1 -1
  80. package/dist/esm/lib/matchers.js +1 -1
  81. package/dist/esm/lib/matchers.js.map +1 -1
  82. package/dist/esm/lib/primitives.d.ts +1 -0
  83. package/dist/esm/lib/primitives.d.ts.map +1 -1
  84. package/dist/esm/lib/primitives.js +17 -0
  85. package/dist/esm/lib/primitives.js.map +1 -1
  86. package/dist/esm/lib/retries.js +7 -0
  87. package/dist/esm/lib/retries.js.map +1 -1
  88. package/dist/esm/lib/sdks.d.ts.map +1 -1
  89. package/dist/esm/lib/sdks.js +50 -16
  90. package/dist/esm/lib/sdks.js.map +1 -1
  91. package/dist/esm/models/client-credentials-grant-request.d.ts +25 -0
  92. package/dist/esm/models/client-credentials-grant-request.d.ts.map +1 -0
  93. package/dist/esm/models/client-credentials-grant-request.js +21 -0
  94. package/dist/esm/models/client-credentials-grant-request.js.map +1 -0
  95. package/dist/esm/models/index.d.ts +2 -0
  96. package/dist/esm/models/index.d.ts.map +1 -1
  97. package/dist/esm/models/index.js +2 -0
  98. package/dist/esm/models/index.js.map +1 -1
  99. package/dist/esm/models/operations/fetch-interaction.d.ts +41 -12
  100. package/dist/esm/models/operations/fetch-interaction.d.ts.map +1 -1
  101. package/dist/esm/models/operations/fetch-interaction.js +38 -11
  102. package/dist/esm/models/operations/fetch-interaction.js.map +1 -1
  103. package/dist/esm/models/operations/index.d.ts +1 -1
  104. package/dist/esm/models/operations/index.d.ts.map +1 -1
  105. package/dist/esm/models/operations/index.js +1 -1
  106. package/dist/esm/models/operations/index.js.map +1 -1
  107. package/dist/esm/models/operations/post-as-token-oauth2.d.ts +32 -0
  108. package/dist/esm/models/operations/post-as-token-oauth2.d.ts.map +1 -0
  109. package/dist/esm/models/operations/post-as-token-oauth2.js +35 -0
  110. package/dist/esm/models/operations/post-as-token-oauth2.js.map +1 -0
  111. package/dist/esm/models/password-grant-request.d.ts +35 -0
  112. package/dist/esm/models/password-grant-request.d.ts.map +1 -0
  113. package/dist/esm/models/password-grant-request.js +23 -0
  114. package/dist/esm/models/password-grant-request.js.map +1 -0
  115. package/dist/esm/sdk/tokens.d.ts +2 -2
  116. package/dist/esm/sdk/tokens.d.ts.map +1 -1
  117. package/dist/esm/sdk/tokens.js +1 -1
  118. package/dist/esm/sdk/tokens.js.map +1 -1
  119. package/examples/tokensGenerate.example.ts +1 -7
  120. package/jsr.json +1 -1
  121. package/package.json +1 -1
  122. package/src/__tests__/x-gbg-source.test.mjs +59 -0
  123. package/src/funcs/tokens-generate.ts +12 -23
  124. package/src/hooks/registration.ts +4 -4
  125. package/src/hooks/types.ts +1 -0
  126. package/src/hooks/x-gbg-source.ts +70 -0
  127. package/src/lib/config.ts +3 -3
  128. package/src/lib/encodings.ts +1 -1
  129. package/src/lib/env.ts +7 -3
  130. package/src/lib/matchers.ts +1 -1
  131. package/src/lib/primitives.ts +16 -0
  132. package/src/lib/retries.ts +8 -0
  133. package/src/lib/sdks.ts +54 -17
  134. package/src/models/client-credentials-grant-request.ts +57 -0
  135. package/src/models/index.ts +2 -0
  136. package/src/models/operations/fetch-interaction.ts +105 -34
  137. package/src/models/operations/index.ts +1 -1
  138. package/src/models/operations/post-as-token-oauth2.ts +88 -0
  139. package/src/models/password-grant-request.ts +67 -0
  140. package/src/sdk/tokens.ts +3 -5
  141. package/dist/commonjs/lib/dlv.d.ts +0 -14
  142. package/dist/commonjs/lib/dlv.d.ts.map +0 -1
  143. package/dist/commonjs/lib/dlv.js +0 -49
  144. package/dist/commonjs/lib/dlv.js.map +0 -1
  145. package/dist/commonjs/lib/is-plain-object.d.ts +0 -2
  146. package/dist/commonjs/lib/is-plain-object.d.ts.map +0 -1
  147. package/dist/commonjs/lib/is-plain-object.js +0 -41
  148. package/dist/commonjs/lib/is-plain-object.js.map +0 -1
  149. package/dist/commonjs/models/operations/post-auth-realms-go-protocol-openid-connect-token.d.ts +0 -71
  150. package/dist/commonjs/models/operations/post-auth-realms-go-protocol-openid-connect-token.d.ts.map +0 -1
  151. package/dist/commonjs/models/operations/post-auth-realms-go-protocol-openid-connect-token.js.map +0 -1
  152. package/dist/esm/lib/dlv.d.ts +0 -14
  153. package/dist/esm/lib/dlv.d.ts.map +0 -1
  154. package/dist/esm/lib/dlv.js +0 -46
  155. package/dist/esm/lib/dlv.js.map +0 -1
  156. package/dist/esm/lib/is-plain-object.d.ts +0 -2
  157. package/dist/esm/lib/is-plain-object.d.ts.map +0 -1
  158. package/dist/esm/lib/is-plain-object.js +0 -38
  159. package/dist/esm/lib/is-plain-object.js.map +0 -1
  160. package/dist/esm/models/operations/post-auth-realms-go-protocol-openid-connect-token.d.ts +0 -71
  161. package/dist/esm/models/operations/post-auth-realms-go-protocol-openid-connect-token.d.ts.map +0 -1
  162. package/dist/esm/models/operations/post-auth-realms-go-protocol-openid-connect-token.js +0 -54
  163. package/dist/esm/models/operations/post-auth-realms-go-protocol-openid-connect-token.js.map +0 -1
  164. package/src/lib/dlv.ts +0 -53
  165. package/src/lib/is-plain-object.ts +0 -43
  166. package/src/models/operations/post-auth-realms-go-protocol-openid-connect-token.ts +0 -150
@@ -22,7 +22,7 @@ import {
22
22
  import { ResponseValidationError } from "../models/errors/response-validation-error.js";
23
23
  import { SDKValidationError } from "../models/errors/sdk-validation-error.js";
24
24
  import * as operations from "../models/operations/index.js";
25
- import { PostAuthRealmsGoProtocolOpenidConnectTokenServerList } from "../models/operations/post-auth-realms-go-protocol-openid-connect-token.js";
25
+ import { PostAsTokenOauth2ServerList } from "../models/operations/post-as-token-oauth2.js";
26
26
  import { APICall, APIPromise } from "../types/async.js";
27
27
  import { Result } from "../types/fp.js";
28
28
 
@@ -30,17 +30,15 @@ import { Result } from "../types/fp.js";
30
30
  * Generate access token
31
31
  *
32
32
  * @remarks
33
- * Get an access token to authenticate API requests. If you're unfamiliar with the authentication process, check out the [authentication guide](/docs/developer-integration/execute-customer-journeys/authenticate) for more details.
33
+ * Get an access token to authenticate API requests. If you're unfamiliar with the authentication process, check out the [authentication guide](/docs/go-v2/developer-integration/execute-customer-journeys/authenticate) for more details.
34
34
  */
35
35
  export function tokensGenerate(
36
36
  client: GoCore,
37
- request?:
38
- | operations.PostAuthRealmsGoProtocolOpenidConnectTokenRequest
39
- | undefined,
37
+ request?: operations.PostAsTokenOauth2Request | undefined,
40
38
  options?: RequestOptions,
41
39
  ): APIPromise<
42
40
  Result<
43
- operations.PostAuthRealmsGoProtocolOpenidConnectTokenResponse,
41
+ operations.PostAsTokenOauth2Response,
44
42
  | GoError
45
43
  | ResponseValidationError
46
44
  | ConnectionError
@@ -60,14 +58,12 @@ export function tokensGenerate(
60
58
 
61
59
  async function $do(
62
60
  client: GoCore,
63
- request?:
64
- | operations.PostAuthRealmsGoProtocolOpenidConnectTokenRequest
65
- | undefined,
61
+ request?: operations.PostAsTokenOauth2Request | undefined,
66
62
  options?: RequestOptions,
67
63
  ): Promise<
68
64
  [
69
65
  Result<
70
- operations.PostAuthRealmsGoProtocolOpenidConnectTokenResponse,
66
+ operations.PostAsTokenOauth2Response,
71
67
  | GoError
72
68
  | ResponseValidationError
73
69
  | ConnectionError
@@ -84,10 +80,7 @@ async function $do(
84
80
  request,
85
81
  (value) =>
86
82
  z.parse(
87
- z.optional(
88
- operations
89
- .PostAuthRealmsGoProtocolOpenidConnectTokenRequest$outboundSchema,
90
- ),
83
+ z.optional(operations.PostAsTokenOauth2Request$outboundSchema),
91
84
  value,
92
85
  ),
93
86
  "Input validation failed",
@@ -102,11 +95,11 @@ async function $do(
102
95
  }).join("&");
103
96
 
104
97
  const baseURL = options?.serverURL
105
- || pathToFunc(PostAuthRealmsGoProtocolOpenidConnectTokenServerList[0], {
98
+ || pathToFunc(PostAsTokenOauth2ServerList[0], {
106
99
  charEncoding: "percent",
107
100
  })();
108
101
 
109
- const path = pathToFunc("/auth/realms/go/protocol/openid-connect/token")();
102
+ const path = pathToFunc("/as/token.oauth2")();
110
103
 
111
104
  const headers = new Headers(compactMap({
112
105
  "Content-Type": "application/x-www-form-urlencoded",
@@ -116,7 +109,7 @@ async function $do(
116
109
  const context = {
117
110
  options: client._options,
118
111
  baseURL: baseURL ?? "",
119
- operationID: "post_/auth/realms/go/protocol/openid-connect/token",
112
+ operationID: "post_/as/token.oauth2",
120
113
  oAuth2Scopes: null,
121
114
 
122
115
  resolvedSecurity: null,
@@ -155,7 +148,7 @@ async function $do(
155
148
  const response = doResult.value;
156
149
 
157
150
  const [result] = await M.match<
158
- operations.PostAuthRealmsGoProtocolOpenidConnectTokenResponse,
151
+ operations.PostAsTokenOauth2Response,
159
152
  | GoError
160
153
  | ResponseValidationError
161
154
  | ConnectionError
@@ -165,11 +158,7 @@ async function $do(
165
158
  | UnexpectedClientError
166
159
  | SDKValidationError
167
160
  >(
168
- M.json(
169
- 200,
170
- operations
171
- .PostAuthRealmsGoProtocolOpenidConnectTokenResponse$inboundSchema,
172
- ),
161
+ M.json(200, operations.PostAsTokenOauth2Response$inboundSchema),
173
162
  M.fail([400, 401, "4XX"]),
174
163
  M.fail("5XX"),
175
164
  )(response, req);
@@ -1,4 +1,5 @@
1
1
  import { Hooks } from "./types.js";
2
+ import { GbgSourceHook } from "./x-gbg-source.js";
2
3
 
3
4
  /*
4
5
  * This file is only ever generated once on the first generation and then is free to be modified.
@@ -6,9 +7,8 @@ import { Hooks } from "./types.js";
6
7
  * in this file or in separate files in the hooks folder.
7
8
  */
8
9
 
9
- // @ts-expect-error remove this line when you add your first hook and hooks is used
10
10
  export function initHooks(hooks: Hooks) {
11
- // Add hooks by calling hooks.register{ClientInit/BeforeCreateRequest/BeforeRequest/AfterSuccess/AfterError}Hook
12
- // with an instance of a hook that implements that specific Hook interface
13
- // Hooks are registered per SDK instance, and are valid for the lifetime of the SDK instance
11
+ // Stamp an X-GBG-Source usage-tracking header on every outgoing request.
12
+ // See ./x-gbg-source.ts (GGO-16030 / issue #34).
13
+ hooks.registerBeforeCreateRequestHook(new GbgSourceHook());
14
14
  }
@@ -15,6 +15,7 @@ export type HookContext = {
15
15
  retryConfig: RetryConfig;
16
16
  resolvedSecurity: SecurityState | null;
17
17
  options: SDKOptions;
18
+ timeoutMs?: number;
18
19
  };
19
20
 
20
21
  export type Awaitable<T> = T | Promise<T>;
@@ -0,0 +1,70 @@
1
+ /*
2
+ * Custom hook: stamps an `X-GBG-Source` usage-tracking header on every
3
+ * outgoing request.
4
+ *
5
+ * This file is NOT managed by Speakeasy — it is not tracked in
6
+ * `.speakeasy/gen.lock`, and it is imported from `registration.ts` which
7
+ * Speakeasy generates only once. Both therefore survive the weekly forced SDK
8
+ * regeneration. Do not move this logic into generated files (`config.ts`,
9
+ * `sdks.ts`, `index.ts`, `package.json`): those are overwritten on regen.
10
+ *
11
+ * See GGO-16030 / GitHub issue #34.
12
+ */
13
+
14
+ import { SDK_METADATA, SDKOptions } from "../lib/config.js";
15
+ import { RequestInput } from "../lib/http.js";
16
+ import {
17
+ BeforeCreateRequestContext,
18
+ BeforeCreateRequestHook,
19
+ } from "./types.js";
20
+
21
+ /** The usage-tracking header sent on every request. */
22
+ export const X_GBG_SOURCE_HEADER = "X-GBG-Source";
23
+
24
+ /**
25
+ * SDK options extended with the optional `source` override. Use this to get
26
+ * type-safety for the client-creation override without depending on the
27
+ * regenerated `SDKOptions` declaration:
28
+ *
29
+ * ```ts
30
+ * import { Go } from "@gbg/go-core";
31
+ * import type { GoOptions } from "@gbg/go-core/hooks/x-gbg-source";
32
+ *
33
+ * const sdk = new Go({ source: "acme-portal" } satisfies GoOptions);
34
+ * ```
35
+ */
36
+ export type GoOptions = SDKOptions & {
37
+ /**
38
+ * Value sent in the `X-GBG-Source` header on every request, identifying the
39
+ * integration making the call. Defaults to the SDK's user-agent string. Can
40
+ * also be overridden per-request via `RequestOptions.headers`.
41
+ */
42
+ source?: string | undefined;
43
+ };
44
+
45
+ /**
46
+ * Sets the `X-GBG-Source` header on every request. Precedence, highest first:
47
+ *
48
+ * 1. a per-request header (set via `RequestOptions.headers`) — left untouched
49
+ * 2. the client-creation `source` option
50
+ * 3. the SDK user-agent string (auto-tracks the SDK version)
51
+ */
52
+ export class GbgSourceHook implements BeforeCreateRequestHook {
53
+ beforeCreateRequest(
54
+ hookCtx: BeforeCreateRequestContext,
55
+ input: RequestInput,
56
+ ): RequestInput {
57
+ const options = input.options ?? {};
58
+ const headers = new Headers(options.headers);
59
+
60
+ // Respect a per-request override if one was already set on the request.
61
+ if (!headers.has(X_GBG_SOURCE_HEADER)) {
62
+ const source = (hookCtx.options as GoOptions).source;
63
+ headers.set(X_GBG_SOURCE_HEADER, source ?? SDK_METADATA.userAgent);
64
+ }
65
+
66
+ options.headers = headers;
67
+ input.options = options;
68
+ return input;
69
+ }
70
+ }
package/src/lib/config.ts CHANGED
@@ -60,8 +60,8 @@ export function serverURLFromOptions(options: SDKOptions): URL | null {
60
60
  export const SDK_METADATA = {
61
61
  language: "typescript",
62
62
  openapiDocVersion: "1.0.0",
63
- sdkVersion: "0.0.1-alpha.24",
64
- genVersion: "2.886.1",
63
+ sdkVersion: "0.0.1-alpha.26",
64
+ genVersion: "2.915.1",
65
65
  userAgent:
66
- "speakeasy-sdk/typescript 0.0.1-alpha.24 2.886.1 1.0.0 @gbg/go-core",
66
+ "speakeasy-sdk/typescript 0.0.1-alpha.26 2.915.1 1.0.0 @gbg/go-core",
67
67
  } as const;
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { bytesToBase64 } from "./base64.js";
6
- import { isPlainObject } from "./is-plain-object.js";
6
+ import { isPlainObject } from "./primitives.js";
7
7
 
8
8
  export class EncodingError extends Error {
9
9
  constructor(message: string) {
package/src/lib/env.ts CHANGED
@@ -3,7 +3,6 @@
3
3
  */
4
4
 
5
5
  import * as z from "zod/v4-mini";
6
- import { dlv } from "./dlv.js";
7
6
 
8
7
  export interface Env {
9
8
  GO_CUSTOMER_ACCESS?: string | undefined;
@@ -38,11 +37,16 @@ export function env(): Env {
38
37
  return envMemo;
39
38
  }
40
39
 
40
+ const globals = globalThis as {
41
+ Deno?: { env?: { toObject?: () => Record<string, string | undefined> } };
42
+ process?: { env?: Record<string, string | undefined> };
43
+ };
44
+
41
45
  let envObject: Record<string, unknown> = {};
42
46
  if (isDeno()) {
43
- envObject = (globalThis as any).Deno?.env?.toObject?.() ?? {};
47
+ envObject = globals.Deno?.env?.toObject?.() ?? {};
44
48
  } else {
45
- envObject = dlv(globalThis, "process.env") ?? {};
49
+ envObject = globals.process?.env ?? {};
46
50
  }
47
51
 
48
52
  envMemo = envSchema.parse(envObject);
@@ -6,7 +6,7 @@ import { GoDefaultError } from "../models/errors/go-default-error.js";
6
6
  import { ResponseValidationError } from "../models/errors/response-validation-error.js";
7
7
  import { ERR, OK, Result } from "../types/fp.js";
8
8
  import { matchResponse, matchStatusCode, StatusCodePredicate } from "./http.js";
9
- import { isPlainObject } from "./is-plain-object.js";
9
+ import { isPlainObject } from "./primitives.js";
10
10
 
11
11
  export type Encoding =
12
12
  | "jsonl"
@@ -148,3 +148,19 @@ export function allRequired<V extends Record<string, unknown>>(
148
148
 
149
149
  return v as ReturnType<typeof allRequired<V>>;
150
150
  }
151
+
152
+ export function isPlainObject(
153
+ value: unknown,
154
+ ): value is Record<string, unknown> {
155
+ if (value === null || typeof value !== "object") return false;
156
+ if (Object.prototype.toString.call(value) !== "[object Object]") return false;
157
+ const proto = Object.getPrototypeOf(value);
158
+ if (proto === null || proto === Object.prototype) return true;
159
+ // cross-realm plain objects (vm contexts, iframes) inherit from a
160
+ // different realm's Object.prototype, which itself has a null prototype
161
+ try {
162
+ return Object.getPrototypeOf(proto) === null;
163
+ } catch {
164
+ return false;
165
+ }
166
+ }
@@ -194,6 +194,14 @@ async function retryBackoff(
194
194
  }
195
195
 
196
196
  function retryIntervalFromResponse(res: Response): number {
197
+ const retryAfterMsVal = res.headers.get("retry-after-ms");
198
+ if (retryAfterMsVal) {
199
+ const parsedMs = Number(retryAfterMsVal);
200
+ if (Number.isFinite(parsedMs) && parsedMs >= 0) {
201
+ return parsedMs;
202
+ }
203
+ }
204
+
197
205
  const retryVal = res.headers.get("retry-after") || "";
198
206
  if (!retryVal) {
199
207
  return 0;
package/src/lib/sdks.ts CHANGED
@@ -24,6 +24,7 @@ import {
24
24
  matchContentType,
25
25
  } from "./http.js";
26
26
  import { Logger } from "./logger.js";
27
+ import { combineSignals } from "./primitives.js";
27
28
  import { retry, RetryConfig } from "./retries.js";
28
29
  import { SecurityState } from "./security.js";
29
30
 
@@ -131,27 +132,55 @@ export class ClientSDK {
131
132
  if (path) {
132
133
  baseURL.pathname = baseURL.pathname.replace(/\/+$/, "") + "/";
133
134
  reqURL = new URL(path, baseURL);
135
+ if (!reqURL.search && baseURL.search) {
136
+ reqURL.search = baseURL.search;
137
+ }
134
138
  } else {
135
139
  reqURL = baseURL;
136
140
  }
137
141
  reqURL.hash = "";
138
142
 
139
- let finalQuery = query || "";
140
-
141
- const secQuery: string[] = [];
142
- for (const [k, v] of Object.entries(security?.queryParams || {})) {
143
- const q = encodeForm(k, v, { charEncoding: "percent" });
144
- if (typeof q !== "undefined") {
145
- secQuery.push(q);
143
+ // Appends already-encoded query pairs to a query string, replacing any
144
+ // existing pairs with the same key so later sources take precedence.
145
+ const mergeQuery = (current: string, additions: string): string => {
146
+ if (!additions) {
147
+ return current;
146
148
  }
147
- }
148
- if (secQuery.length) {
149
- finalQuery += `&${secQuery.join("&")}`;
150
- }
149
+ const additionKeys = new Set(
150
+ additions
151
+ .split("&")
152
+ .filter((pair) => pair !== "")
153
+ .map((pair) => pair.split("=")[0] ?? ""),
154
+ );
155
+ const kept = current.split("&").filter((pair) => {
156
+ return pair !== "" && !additionKeys.has(pair.split("=")[0] ?? "");
157
+ });
158
+ return [...kept, additions].join("&");
159
+ };
160
+
161
+ const encodeQueryRecord = (record: Record<string, unknown>): string => {
162
+ return Object.entries(record)
163
+ .map(([k, v]) => {
164
+ if (v == null) {
165
+ return undefined;
166
+ }
167
+ const value = v;
168
+ return encodeForm(k, value, {
169
+ explode: Array.isArray(value),
170
+ charEncoding: "percent",
171
+ });
172
+ })
173
+ .filter((pair): pair is string => typeof pair !== "undefined")
174
+ .join("&");
175
+ };
176
+
177
+ const finalQuery = [
178
+ query || "",
179
+ encodeQueryRecord(security?.queryParams || {}),
180
+ ].reduce(mergeQuery, reqURL.search.slice(1));
151
181
 
152
182
  if (finalQuery) {
153
- const q = finalQuery.startsWith("&") ? finalQuery.slice(1) : finalQuery;
154
- reqURL.search = `?${q}`;
183
+ reqURL.search = `?${finalQuery}`;
155
184
  }
156
185
 
157
186
  const headers = new Headers(opHeaders);
@@ -197,9 +226,8 @@ export class ClientSDK {
197
226
  ...options?.fetchOptions,
198
227
  ...options,
199
228
  };
200
- if (!fetchOptions?.signal && conf.timeoutMs && conf.timeoutMs > 0) {
201
- const timeoutSignal = AbortSignal.timeout(conf.timeoutMs);
202
- fetchOptions.signal = timeoutSignal;
229
+ if (!fetchOptions?.signal && conf.timeoutMs != null && conf.timeoutMs > 0) {
230
+ context.timeoutMs = conf.timeoutMs;
203
231
  }
204
232
 
205
233
  if (conf.body instanceof ReadableStream) {
@@ -246,10 +274,19 @@ export class ClientSDK {
246
274
  >
247
275
  > {
248
276
  const { context, isErrorStatusCode } = options;
277
+ const timeoutMs = context.timeoutMs;
249
278
 
250
279
  return retry(
251
280
  async () => {
252
- const req = await this.#hooks.beforeRequest(context, request.clone());
281
+ const cloned = request.clone();
282
+ let attempt = cloned;
283
+ if (timeoutMs != null && timeoutMs > 0) {
284
+ const timeoutSignal = AbortSignal.timeout(timeoutMs);
285
+ const combined = combineSignals(cloned.signal, timeoutSignal)
286
+ ?? timeoutSignal;
287
+ attempt = new Request(cloned, { signal: combined });
288
+ }
289
+ const req = await this.#hooks.beforeRequest(context, attempt);
253
290
  await logRequest(this.#logger, req).catch((e) =>
254
291
  this.#logger?.log("Failed to log request:", e)
255
292
  );
@@ -0,0 +1,57 @@
1
+ /*
2
+ * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
3
+ */
4
+
5
+ import * as z from "zod/v4-mini";
6
+ import { remap as remap$ } from "../lib/primitives.js";
7
+
8
+ export type ClientCredentialsGrantRequest = {
9
+ /**
10
+ * The client ID assigned to your organization.
11
+ */
12
+ clientId: string;
13
+ /**
14
+ * The client secret assigned to your organization.
15
+ */
16
+ clientSecret: string;
17
+ /**
18
+ * Must always be set to 'client_credentials'.
19
+ */
20
+ grantType: "client_credentials";
21
+ };
22
+
23
+ /** @internal */
24
+ export type ClientCredentialsGrantRequest$Outbound = {
25
+ client_id: string;
26
+ client_secret: string;
27
+ grant_type: "client_credentials";
28
+ };
29
+
30
+ /** @internal */
31
+ export const ClientCredentialsGrantRequest$outboundSchema: z.ZodMiniType<
32
+ ClientCredentialsGrantRequest$Outbound,
33
+ ClientCredentialsGrantRequest
34
+ > = z.pipe(
35
+ z.object({
36
+ clientId: z.string(),
37
+ clientSecret: z.string(),
38
+ grantType: z.literal("client_credentials"),
39
+ }),
40
+ z.transform((v) => {
41
+ return remap$(v, {
42
+ clientId: "client_id",
43
+ clientSecret: "client_secret",
44
+ grantType: "grant_type",
45
+ });
46
+ }),
47
+ );
48
+
49
+ export function clientCredentialsGrantRequestToJSON(
50
+ clientCredentialsGrantRequest: ClientCredentialsGrantRequest,
51
+ ): string {
52
+ return JSON.stringify(
53
+ ClientCredentialsGrantRequest$outboundSchema.parse(
54
+ clientCredentialsGrantRequest,
55
+ ),
56
+ );
57
+ }
@@ -2,4 +2,6 @@
2
2
  * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
3
3
  */
4
4
 
5
+ export * from "./client-credentials-grant-request.js";
6
+ export * from "./password-grant-request.js";
5
7
  export * from "./security.js";