@roarkanalytics/sdk 2.21.1 → 2.22.0

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 (348) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +78 -46
  3. package/api-promise.d.mts +1 -46
  4. package/api-promise.d.mts.map +1 -1
  5. package/api-promise.d.ts +1 -46
  6. package/api-promise.d.ts.map +1 -1
  7. package/api-promise.js +3 -81
  8. package/api-promise.js.map +1 -1
  9. package/api-promise.mjs +1 -79
  10. package/api-promise.mjs.map +1 -1
  11. package/client.d.mts +25 -30
  12. package/client.d.mts.map +1 -1
  13. package/client.d.ts +25 -30
  14. package/client.d.ts.map +1 -1
  15. package/client.js +150 -132
  16. package/client.js.map +1 -1
  17. package/client.mjs +145 -104
  18. package/client.mjs.map +1 -1
  19. package/core/api-promise.d.mts +46 -0
  20. package/core/api-promise.d.mts.map +1 -0
  21. package/core/api-promise.d.ts +46 -0
  22. package/core/api-promise.d.ts.map +1 -0
  23. package/core/api-promise.js +74 -0
  24. package/core/api-promise.js.map +1 -0
  25. package/core/api-promise.mjs +70 -0
  26. package/core/api-promise.mjs.map +1 -0
  27. package/core/error.d.mts +46 -0
  28. package/core/error.d.mts.map +1 -0
  29. package/core/error.d.ts +46 -0
  30. package/core/error.d.ts.map +1 -0
  31. package/core/error.js +113 -0
  32. package/core/error.js.map +1 -0
  33. package/core/error.mjs +97 -0
  34. package/core/error.mjs.map +1 -0
  35. package/core/resource.d.mts +6 -0
  36. package/core/resource.d.mts.map +1 -0
  37. package/core/resource.d.ts +6 -0
  38. package/core/resource.d.ts.map +1 -0
  39. package/core/resource.js +11 -0
  40. package/core/resource.js.map +1 -0
  41. package/core/resource.mjs +7 -0
  42. package/core/resource.mjs.map +1 -0
  43. package/core/uploads.d.mts +3 -0
  44. package/core/uploads.d.mts.map +1 -0
  45. package/core/uploads.d.ts +3 -0
  46. package/core/uploads.d.ts.map +1 -0
  47. package/core/uploads.js +6 -0
  48. package/core/uploads.js.map +1 -0
  49. package/core/uploads.mjs +2 -0
  50. package/core/uploads.mjs.map +1 -0
  51. package/error.d.mts +1 -46
  52. package/error.d.mts.map +1 -1
  53. package/error.d.ts +1 -46
  54. package/error.d.ts.map +1 -1
  55. package/error.js +3 -110
  56. package/error.js.map +1 -1
  57. package/error.mjs +1 -96
  58. package/error.mjs.map +1 -1
  59. package/index.d.mts +6 -6
  60. package/index.d.ts +3 -3
  61. package/index.js +3 -3
  62. package/index.js.map +1 -1
  63. package/index.mjs +3 -3
  64. package/internal/builtin-types.d.mts +11 -3
  65. package/internal/builtin-types.d.mts.map +1 -1
  66. package/internal/builtin-types.d.ts +11 -3
  67. package/internal/builtin-types.d.ts.map +1 -1
  68. package/internal/detect-platform.js +3 -3
  69. package/internal/detect-platform.js.map +1 -1
  70. package/internal/detect-platform.mjs +3 -3
  71. package/internal/detect-platform.mjs.map +1 -1
  72. package/internal/errors.d.mts.map +1 -1
  73. package/internal/errors.d.ts.map +1 -1
  74. package/internal/errors.js +17 -2
  75. package/internal/errors.js.map +1 -1
  76. package/internal/errors.mjs +15 -0
  77. package/internal/errors.mjs.map +1 -1
  78. package/internal/headers.d.mts +1 -2
  79. package/internal/headers.d.mts.map +1 -1
  80. package/internal/headers.d.ts +1 -2
  81. package/internal/headers.d.ts.map +1 -1
  82. package/internal/headers.js +7 -5
  83. package/internal/headers.js.map +1 -1
  84. package/internal/headers.mjs +7 -5
  85. package/internal/headers.mjs.map +1 -1
  86. package/internal/parse.d.mts +3 -1
  87. package/internal/parse.d.mts.map +1 -1
  88. package/internal/parse.d.ts +3 -1
  89. package/internal/parse.d.ts.map +1 -1
  90. package/internal/parse.js +33 -21
  91. package/internal/parse.js.map +1 -1
  92. package/internal/parse.mjs +33 -20
  93. package/internal/parse.mjs.map +1 -1
  94. package/internal/qs/formats.d.mts +1 -0
  95. package/internal/qs/formats.d.mts.map +1 -1
  96. package/internal/qs/formats.d.ts +1 -0
  97. package/internal/qs/formats.d.ts.map +1 -1
  98. package/internal/qs/formats.js +4 -2
  99. package/internal/qs/formats.js.map +1 -1
  100. package/internal/qs/formats.mjs +2 -1
  101. package/internal/qs/formats.mjs.map +1 -1
  102. package/internal/qs/stringify.d.mts.map +1 -1
  103. package/internal/qs/stringify.d.ts.map +1 -1
  104. package/internal/qs/stringify.js +16 -19
  105. package/internal/qs/stringify.js.map +1 -1
  106. package/internal/qs/stringify.mjs +17 -19
  107. package/internal/qs/stringify.mjs.map +1 -1
  108. package/internal/qs/utils.d.mts +1 -0
  109. package/internal/qs/utils.d.mts.map +1 -1
  110. package/internal/qs/utils.d.ts +1 -0
  111. package/internal/qs/utils.d.ts.map +1 -1
  112. package/internal/qs/utils.js +22 -21
  113. package/internal/qs/utils.js.map +1 -1
  114. package/internal/qs/utils.mjs +12 -12
  115. package/internal/qs/utils.mjs.map +1 -1
  116. package/internal/request-options.d.mts +43 -2
  117. package/internal/request-options.d.mts.map +1 -1
  118. package/internal/request-options.d.ts +43 -2
  119. package/internal/request-options.d.ts.map +1 -1
  120. package/internal/request-options.js +1 -26
  121. package/internal/request-options.js.map +1 -1
  122. package/internal/request-options.mjs +0 -24
  123. package/internal/request-options.mjs.map +1 -1
  124. package/internal/shim-types.d.mts +11 -22
  125. package/internal/shim-types.d.mts.map +1 -0
  126. package/internal/shim-types.d.ts +11 -22
  127. package/internal/shim-types.d.ts.map +1 -0
  128. package/internal/shim-types.js +4 -0
  129. package/internal/shim-types.js.map +1 -0
  130. package/internal/shim-types.mjs +3 -0
  131. package/internal/shim-types.mjs.map +1 -0
  132. package/internal/shims.d.mts +7 -48
  133. package/internal/shims.d.mts.map +1 -1
  134. package/internal/shims.d.ts +7 -48
  135. package/internal/shims.d.ts.map +1 -1
  136. package/internal/shims.js +21 -30
  137. package/internal/shims.js.map +1 -1
  138. package/internal/shims.mjs +16 -23
  139. package/internal/shims.mjs.map +1 -1
  140. package/internal/to-file.d.mts +45 -0
  141. package/internal/to-file.d.mts.map +1 -0
  142. package/internal/to-file.d.ts +45 -0
  143. package/internal/to-file.d.ts.map +1 -0
  144. package/internal/to-file.js +91 -0
  145. package/internal/to-file.js.map +1 -0
  146. package/internal/to-file.mjs +88 -0
  147. package/internal/to-file.mjs.map +1 -0
  148. package/internal/tslib.js +81 -0
  149. package/internal/tslib.mjs +17 -0
  150. package/internal/types.d.mts +14 -13
  151. package/internal/types.d.mts.map +1 -1
  152. package/internal/types.d.ts +14 -13
  153. package/internal/types.d.ts.map +1 -1
  154. package/internal/uploads.d.mts +16 -47
  155. package/internal/uploads.d.mts.map +1 -1
  156. package/internal/uploads.d.ts +16 -47
  157. package/internal/uploads.d.ts.map +1 -1
  158. package/internal/uploads.js +41 -108
  159. package/internal/uploads.js.map +1 -1
  160. package/internal/uploads.mjs +39 -108
  161. package/internal/uploads.mjs.map +1 -1
  162. package/internal/utils/base64.d.mts.map +1 -1
  163. package/internal/utils/base64.d.ts.map +1 -1
  164. package/internal/utils/base64.js +13 -8
  165. package/internal/utils/base64.js.map +1 -1
  166. package/internal/utils/base64.mjs +13 -8
  167. package/internal/utils/base64.mjs.map +1 -1
  168. package/internal/utils/bytes.d.mts +4 -0
  169. package/internal/utils/bytes.d.mts.map +1 -0
  170. package/internal/utils/bytes.d.ts +4 -0
  171. package/internal/utils/bytes.d.ts.map +1 -0
  172. package/internal/utils/bytes.js +31 -0
  173. package/internal/utils/bytes.js.map +1 -0
  174. package/internal/utils/bytes.mjs +26 -0
  175. package/internal/utils/bytes.mjs.map +1 -0
  176. package/internal/utils/env.d.mts.map +1 -1
  177. package/internal/utils/env.d.ts.map +1 -1
  178. package/internal/utils/env.js.map +1 -1
  179. package/internal/utils/env.mjs.map +1 -1
  180. package/internal/utils/log.d.mts +35 -2
  181. package/internal/utils/log.d.mts.map +1 -1
  182. package/internal/utils/log.d.ts +35 -2
  183. package/internal/utils/log.d.ts.map +1 -1
  184. package/internal/utils/log.js +62 -24
  185. package/internal/utils/log.js.map +1 -1
  186. package/internal/utils/log.mjs +58 -22
  187. package/internal/utils/log.mjs.map +1 -1
  188. package/internal/utils/path.d.mts +15 -0
  189. package/internal/utils/path.d.mts.map +1 -0
  190. package/internal/utils/path.d.ts +15 -0
  191. package/internal/utils/path.d.ts.map +1 -0
  192. package/internal/utils/path.js +79 -0
  193. package/internal/utils/path.js.map +1 -0
  194. package/internal/utils/path.mjs +74 -0
  195. package/internal/utils/path.mjs.map +1 -0
  196. package/internal/utils/sleep.d.mts.map +1 -1
  197. package/internal/utils/sleep.d.ts.map +1 -1
  198. package/internal/utils/uuid.d.mts +1 -1
  199. package/internal/utils/uuid.d.mts.map +1 -1
  200. package/internal/utils/uuid.d.ts +1 -1
  201. package/internal/utils/uuid.d.ts.map +1 -1
  202. package/internal/utils/uuid.js +10 -6
  203. package/internal/utils/uuid.js.map +1 -1
  204. package/internal/utils/uuid.mjs +9 -5
  205. package/internal/utils/uuid.mjs.map +1 -1
  206. package/internal/utils/values.d.mts +4 -1
  207. package/internal/utils/values.d.mts.map +1 -1
  208. package/internal/utils/values.d.ts +4 -1
  209. package/internal/utils/values.d.ts.map +1 -1
  210. package/internal/utils/values.js +21 -9
  211. package/internal/utils/values.js.map +1 -1
  212. package/internal/utils/values.mjs +14 -4
  213. package/internal/utils/values.mjs.map +1 -1
  214. package/internal/utils.js +7 -20
  215. package/internal/utils.js.map +1 -1
  216. package/package.json +31 -13
  217. package/resource.d.mts +1 -5
  218. package/resource.d.mts.map +1 -1
  219. package/resource.d.ts +1 -5
  220. package/resource.d.ts.map +1 -1
  221. package/resource.js +3 -8
  222. package/resource.js.map +1 -1
  223. package/resource.mjs +1 -6
  224. package/resource.mjs.map +1 -1
  225. package/resources/call.d.mts +17 -7
  226. package/resources/call.d.mts.map +1 -1
  227. package/resources/call.d.ts +17 -7
  228. package/resources/call.d.ts.map +1 -1
  229. package/resources/call.js +6 -5
  230. package/resources/call.js.map +1 -1
  231. package/resources/call.mjs +6 -5
  232. package/resources/call.mjs.map +1 -1
  233. package/resources/evaluation.d.mts +20 -8
  234. package/resources/evaluation.d.mts.map +1 -1
  235. package/resources/evaluation.d.ts +20 -8
  236. package/resources/evaluation.d.ts.map +1 -1
  237. package/resources/evaluation.js +5 -4
  238. package/resources/evaluation.js.map +1 -1
  239. package/resources/evaluation.mjs +5 -4
  240. package/resources/evaluation.mjs.map +1 -1
  241. package/resources/health.d.mts +2 -2
  242. package/resources/health.d.ts +2 -2
  243. package/resources/health.js +1 -1
  244. package/resources/health.js.map +1 -1
  245. package/resources/health.mjs +1 -1
  246. package/resources/integrations.d.mts +39 -6
  247. package/resources/integrations.d.mts.map +1 -1
  248. package/resources/integrations.d.ts +39 -6
  249. package/resources/integrations.d.ts.map +1 -1
  250. package/resources/integrations.js +26 -1
  251. package/resources/integrations.js.map +1 -1
  252. package/resources/integrations.mjs +26 -1
  253. package/resources/integrations.mjs.map +1 -1
  254. package/resources/metric.d.mts +2 -2
  255. package/resources/metric.d.ts +2 -2
  256. package/resources/metric.js +1 -1
  257. package/resources/metric.js.map +1 -1
  258. package/resources/metric.mjs +1 -1
  259. package/resources/persona.d.mts +45 -8
  260. package/resources/persona.d.mts.map +1 -1
  261. package/resources/persona.d.ts +45 -8
  262. package/resources/persona.d.ts.map +1 -1
  263. package/resources/persona.js +29 -3
  264. package/resources/persona.js.map +1 -1
  265. package/resources/persona.mjs +29 -3
  266. package/resources/persona.mjs.map +1 -1
  267. package/resources/simulation.d.mts +51 -5
  268. package/resources/simulation.d.mts.map +1 -1
  269. package/resources/simulation.d.ts +51 -5
  270. package/resources/simulation.d.ts.map +1 -1
  271. package/resources/simulation.js +45 -4
  272. package/resources/simulation.js.map +1 -1
  273. package/resources/simulation.mjs +45 -4
  274. package/resources/simulation.mjs.map +1 -1
  275. package/resources.d.mts +2 -0
  276. package/resources.d.mts.map +1 -0
  277. package/resources.d.ts +2 -0
  278. package/resources.d.ts.map +1 -0
  279. package/resources.js +5 -0
  280. package/resources.js.map +1 -0
  281. package/resources.mjs +2 -0
  282. package/resources.mjs.map +1 -0
  283. package/src/api-promise.ts +2 -92
  284. package/src/client.ts +207 -116
  285. package/src/core/README.md +3 -0
  286. package/src/core/api-promise.ts +92 -0
  287. package/src/core/error.ts +130 -0
  288. package/src/core/resource.ts +11 -0
  289. package/src/core/uploads.ts +2 -0
  290. package/src/error.ts +2 -130
  291. package/src/index.ts +3 -3
  292. package/src/internal/README.md +3 -0
  293. package/src/internal/builtin-types.ts +14 -0
  294. package/src/internal/detect-platform.ts +3 -3
  295. package/src/internal/errors.ts +11 -0
  296. package/src/internal/headers.ts +9 -8
  297. package/src/internal/parse.ts +43 -28
  298. package/src/internal/qs/formats.ts +2 -1
  299. package/src/internal/qs/stringify.ts +17 -20
  300. package/src/internal/qs/utils.ts +14 -14
  301. package/src/internal/request-options.ts +55 -31
  302. package/src/internal/shim-types.ts +26 -0
  303. package/src/internal/shims.ts +20 -58
  304. package/src/internal/to-file.ts +154 -0
  305. package/src/internal/types.ts +14 -17
  306. package/src/internal/uploads.ts +60 -180
  307. package/src/internal/utils/base64.ts +14 -11
  308. package/src/internal/utils/bytes.ts +32 -0
  309. package/src/internal/utils/log.ts +100 -23
  310. package/src/internal/utils/path.ts +88 -0
  311. package/src/internal/utils/uuid.ts +10 -6
  312. package/src/internal/utils/values.ts +16 -5
  313. package/src/resource.ts +2 -11
  314. package/src/resources/call.ts +12 -11
  315. package/src/resources/evaluation.ts +12 -11
  316. package/src/resources/health.ts +2 -2
  317. package/src/resources/integrations.ts +31 -6
  318. package/src/resources/metric.ts +2 -2
  319. package/src/resources/persona.ts +36 -10
  320. package/src/resources/simulation.ts +49 -8
  321. package/src/resources.ts +1 -0
  322. package/src/uploads.ts +2 -1
  323. package/src/version.ts +1 -1
  324. package/uploads.d.mts +1 -1
  325. package/uploads.d.mts.map +1 -1
  326. package/uploads.d.ts +1 -1
  327. package/uploads.d.ts.map +1 -1
  328. package/uploads.js +3 -3
  329. package/uploads.js.map +1 -1
  330. package/uploads.mjs +1 -1
  331. package/uploads.mjs.map +1 -1
  332. package/version.d.mts +1 -1
  333. package/version.d.ts +1 -1
  334. package/version.js +1 -1
  335. package/version.mjs +1 -1
  336. package/internal/polyfill/crypto.node.d.ts +0 -10
  337. package/internal/polyfill/crypto.node.js +0 -11
  338. package/internal/polyfill/crypto.node.mjs +0 -2
  339. package/internal/polyfill/file.node.d.ts +0 -9
  340. package/internal/polyfill/file.node.js +0 -17
  341. package/internal/polyfill/file.node.mjs +0 -9
  342. package/src/internal/polyfill/crypto.node.d.ts +0 -10
  343. package/src/internal/polyfill/crypto.node.js +0 -11
  344. package/src/internal/polyfill/crypto.node.mjs +0 -2
  345. package/src/internal/polyfill/file.node.d.ts +0 -9
  346. package/src/internal/polyfill/file.node.js +0 -17
  347. package/src/internal/polyfill/file.node.mjs +0 -9
  348. package/src/internal/shim-types.d.ts +0 -28
package/src/client.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  import type { RequestInit, RequestInfo, BodyInit } from './internal/builtin-types';
4
- import type { HTTPMethod, PromiseOrValue, MergedRequestInit } from './internal/types';
4
+ import type { HTTPMethod, PromiseOrValue, MergedRequestInit, FinalizedRequestInit } from './internal/types';
5
5
  import { uuid4 } from './internal/utils/uuid';
6
- import { validatePositiveInteger, isAbsoluteURL } from './internal/utils/values';
6
+ import { validatePositiveInteger, isAbsoluteURL, safeJSON } from './internal/utils/values';
7
7
  import { sleep } from './internal/utils/sleep';
8
+ export type { Logger, LogLevel } from './internal/utils/log';
8
9
  import { castToError, isAbortError } from './internal/errors';
9
10
  import type { APIResponseProps } from './internal/parse';
10
11
  import { getPlatformHeaders } from './internal/detect-platform';
@@ -12,13 +13,10 @@ import * as Shims from './internal/shims';
12
13
  import * as Opts from './internal/request-options';
13
14
  import * as qs from './internal/qs';
14
15
  import { VERSION } from './version';
15
- import * as Errors from './error';
16
- import * as Uploads from './uploads';
16
+ import * as Errors from './core/error';
17
+ import * as Uploads from './core/uploads';
17
18
  import * as API from './resources/index';
18
- import { APIPromise } from './api-promise';
19
- import { type Fetch } from './internal/builtin-types';
20
- import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers';
21
- import { FinalRequestOptions, RequestOptions } from './internal/request-options';
19
+ import { APIPromise } from './core/api-promise';
22
20
  import {
23
21
  Call,
24
22
  CallCreateParams,
@@ -73,37 +71,19 @@ import {
73
71
  SimulationLookupSimulationJobResponse,
74
72
  SimulationStartRunPlanJobResponse,
75
73
  } from './resources/simulation';
74
+ import { type Fetch } from './internal/builtin-types';
75
+ import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers';
76
+ import { FinalRequestOptions, RequestOptions } from './internal/request-options';
76
77
  import { readEnv } from './internal/utils/env';
77
- import { logger } from './internal/utils/log';
78
+ import {
79
+ type LogLevel,
80
+ type Logger,
81
+ formatRequestDetails,
82
+ loggerFor,
83
+ parseLogLevel,
84
+ } from './internal/utils/log';
78
85
  import { isEmptyObj } from './internal/utils/values';
79
86
 
80
- const safeJSON = (text: string) => {
81
- try {
82
- return JSON.parse(text);
83
- } catch (err) {
84
- return undefined;
85
- }
86
- };
87
-
88
- type LogFn = (message: string, ...rest: unknown[]) => void;
89
- export type Logger = {
90
- error: LogFn;
91
- warn: LogFn;
92
- info: LogFn;
93
- debug: LogFn;
94
- };
95
- export type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug';
96
- const isLogLevel = (key: string | undefined): key is LogLevel => {
97
- const levels: Record<LogLevel, true> = {
98
- off: true,
99
- error: true,
100
- warn: true,
101
- info: true,
102
- debug: true,
103
- };
104
- return key! in levels;
105
- };
106
-
107
87
  export interface ClientOptions {
108
88
  /**
109
89
  * JWT token for authentication
@@ -123,6 +103,8 @@ export interface ClientOptions {
123
103
  *
124
104
  * Note that request timeouts are retried by default, so in a worst-case scenario you may wait
125
105
  * much longer than this timeout before the promise succeeds or fails.
106
+ *
107
+ * @unit milliseconds
126
108
  */
127
109
  timeout?: number | undefined;
128
110
  /**
@@ -165,20 +147,18 @@ export interface ClientOptions {
165
147
  /**
166
148
  * Set the log level.
167
149
  *
168
- * Defaults to process.env['ROARK_LOG'].
150
+ * Defaults to process.env['ROARK_LOG'] or 'warn' if it isn't set.
169
151
  */
170
- logLevel?: LogLevel | undefined | null;
152
+ logLevel?: LogLevel | undefined;
171
153
 
172
154
  /**
173
155
  * Set the logger.
174
156
  *
175
157
  * Defaults to globalThis.console.
176
158
  */
177
- logger?: Logger | undefined | null;
159
+ logger?: Logger | undefined;
178
160
  }
179
161
 
180
- type FinalizedRequestInit = RequestInit & { headers: Headers };
181
-
182
162
  /**
183
163
  * API Client for interfacing with the Roark API.
184
164
  */
@@ -188,7 +168,7 @@ export class Roark {
188
168
  baseURL: string;
189
169
  maxRetries: number;
190
170
  timeout: number;
191
- logger: Logger | undefined;
171
+ logger: Logger;
192
172
  logLevel: LogLevel | undefined;
193
173
  fetchOptions: MergedRequestInit | undefined;
194
174
 
@@ -229,14 +209,13 @@ export class Roark {
229
209
  this.baseURL = options.baseURL!;
230
210
  this.timeout = options.timeout ?? Roark.DEFAULT_TIMEOUT /* 1 minute */;
231
211
  this.logger = options.logger ?? console;
232
- if (options.logLevel != null) {
233
- this.logLevel = options.logLevel;
234
- } else {
235
- const envLevel = readEnv('ROARK_LOG');
236
- if (isLogLevel(envLevel)) {
237
- this.logLevel = envLevel;
238
- }
239
- }
212
+ const defaultLogLevel = 'warn';
213
+ // Set default logLevel early so that we can log a warning in parseLogLevel.
214
+ this.logLevel = defaultLogLevel;
215
+ this.logLevel =
216
+ parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ??
217
+ parseLogLevel(readEnv('ROARK_LOG'), "process.env['ROARK_LOG']", this) ??
218
+ defaultLogLevel;
240
219
  this.fetchOptions = options.fetchOptions;
241
220
  this.maxRetries = options.maxRetries ?? 2;
242
221
  this.fetch = options.fetch ?? Shims.getDefaultFetch();
@@ -247,6 +226,32 @@ export class Roark {
247
226
  this.bearerToken = bearerToken;
248
227
  }
249
228
 
229
+ /**
230
+ * Create a new client instance re-using the same options given to the current client with optional overriding.
231
+ */
232
+ withOptions(options: Partial<ClientOptions>): this {
233
+ const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({
234
+ ...this._options,
235
+ baseURL: this.baseURL,
236
+ maxRetries: this.maxRetries,
237
+ timeout: this.timeout,
238
+ logger: this.logger,
239
+ logLevel: this.logLevel,
240
+ fetch: this.fetch,
241
+ fetchOptions: this.fetchOptions,
242
+ bearerToken: this.bearerToken,
243
+ ...options,
244
+ });
245
+ return client;
246
+ }
247
+
248
+ /**
249
+ * Check whether the base URL is set to its default.
250
+ */
251
+ #baseURLOverridden(): boolean {
252
+ return this.baseURL !== 'https://api.roark.ai';
253
+ }
254
+
250
255
  protected defaultQuery(): Record<string, string | undefined> | undefined {
251
256
  return this._options.defaultQuery;
252
257
  }
@@ -255,8 +260,8 @@ export class Roark {
255
260
  return;
256
261
  }
257
262
 
258
- protected authHeaders(opts: FinalRequestOptions): Headers | undefined {
259
- return new Headers({ Authorization: `Bearer ${this.bearerToken}` });
263
+ protected async authHeaders(opts: FinalRequestOptions): Promise<NullableHeaders | undefined> {
264
+ return buildHeaders([{ Authorization: `Bearer ${this.bearerToken}` }]);
260
265
  }
261
266
 
262
267
  protected stringifyQuery(query: Record<string, unknown>): string {
@@ -280,11 +285,16 @@ export class Roark {
280
285
  return Errors.APIError.generate(status, error, message, headers);
281
286
  }
282
287
 
283
- buildURL(path: string, query: Record<string, unknown> | null | undefined): string {
288
+ buildURL(
289
+ path: string,
290
+ query: Record<string, unknown> | null | undefined,
291
+ defaultBaseURL?: string | undefined,
292
+ ): string {
293
+ const baseURL = (!this.#baseURLOverridden() && defaultBaseURL) || this.baseURL;
284
294
  const url =
285
295
  isAbsoluteURL(path) ?
286
296
  new URL(path)
287
- : new URL(this.baseURL + (this.baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));
297
+ : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));
288
298
 
289
299
  const defaultQuery = this.defaultQuery();
290
300
  if (!isEmptyObj(defaultQuery)) {
@@ -298,24 +308,6 @@ export class Roark {
298
308
  return url.toString();
299
309
  }
300
310
 
301
- private calculateContentLength(body: unknown): string | null {
302
- if (typeof body === 'string') {
303
- if (typeof (globalThis as any).Buffer !== 'undefined') {
304
- return (globalThis as any).Buffer.byteLength(body, 'utf8').toString();
305
- }
306
-
307
- if (typeof (globalThis as any).TextEncoder !== 'undefined') {
308
- const encoder = new (globalThis as any).TextEncoder();
309
- const encoded = encoder.encode(body);
310
- return encoded.length.toString();
311
- }
312
- } else if (ArrayBuffer.isView(body)) {
313
- return body.byteLength.toString();
314
- }
315
-
316
- return null;
317
- }
318
-
319
311
  /**
320
312
  * Used as a callback for mutating the given `FinalRequestOptions` object.
321
313
  */
@@ -368,12 +360,13 @@ export class Roark {
368
360
  options: PromiseOrValue<FinalRequestOptions>,
369
361
  remainingRetries: number | null = null,
370
362
  ): APIPromise<Rsp> {
371
- return new APIPromise(this, this.makeRequest(options, remainingRetries));
363
+ return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined));
372
364
  }
373
365
 
374
366
  private async makeRequest(
375
367
  optionsInput: PromiseOrValue<FinalRequestOptions>,
376
368
  retriesRemaining: number | null,
369
+ retryOfRequestLogID: string | undefined,
377
370
  ): Promise<APIResponseProps> {
378
371
  const options = await optionsInput;
379
372
  const maxRetries = options.maxRetries ?? this.maxRetries;
@@ -383,11 +376,27 @@ export class Roark {
383
376
 
384
377
  await this.prepareOptions(options);
385
378
 
386
- const { req, url, timeout } = this.buildRequest(options, { retryCount: maxRetries - retriesRemaining });
379
+ const { req, url, timeout } = await this.buildRequest(options, {
380
+ retryCount: maxRetries - retriesRemaining,
381
+ });
387
382
 
388
383
  await this.prepareRequest(req, { url, options });
389
384
 
390
- logger(this).debug('request', url, options, req.headers);
385
+ /** Not an API request ID, just for correlating local log entries. */
386
+ const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0');
387
+ const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`;
388
+ const startTime = Date.now();
389
+
390
+ loggerFor(this).debug(
391
+ `[${requestLogID}] sending request`,
392
+ formatRequestDetails({
393
+ retryOfRequestLogID,
394
+ method: options.method,
395
+ url,
396
+ options,
397
+ headers: req.headers,
398
+ }),
399
+ );
391
400
 
392
401
  if (options.signal?.aborted) {
393
402
  throw new Errors.APIUserAbortError();
@@ -395,52 +404,120 @@ export class Roark {
395
404
 
396
405
  const controller = new AbortController();
397
406
  const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);
407
+ const headersTime = Date.now();
398
408
 
399
- if (response instanceof Error) {
409
+ if (response instanceof globalThis.Error) {
410
+ const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
400
411
  if (options.signal?.aborted) {
401
412
  throw new Errors.APIUserAbortError();
402
413
  }
403
- if (retriesRemaining) {
404
- return this.retryRequest(options, retriesRemaining);
405
- }
406
- if (isAbortError(response)) {
407
- throw new Errors.APIConnectionTimeoutError();
408
- }
409
414
  // detect native connection timeout errors
410
415
  // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)"
411
416
  // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)"
412
417
  // others do not provide enough information to distinguish timeouts from other connection errors
413
- if (/timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : ''))) {
418
+ const isTimeout =
419
+ isAbortError(response) ||
420
+ /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : ''));
421
+ if (retriesRemaining) {
422
+ loggerFor(this).info(
423
+ `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`,
424
+ );
425
+ loggerFor(this).debug(
426
+ `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`,
427
+ formatRequestDetails({
428
+ retryOfRequestLogID,
429
+ url,
430
+ durationMs: headersTime - startTime,
431
+ message: response.message,
432
+ }),
433
+ );
434
+ return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID);
435
+ }
436
+ loggerFor(this).info(
437
+ `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`,
438
+ );
439
+ loggerFor(this).debug(
440
+ `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`,
441
+ formatRequestDetails({
442
+ retryOfRequestLogID,
443
+ url,
444
+ durationMs: headersTime - startTime,
445
+ message: response.message,
446
+ }),
447
+ );
448
+ if (isTimeout) {
414
449
  throw new Errors.APIConnectionTimeoutError();
415
450
  }
416
451
  throw new Errors.APIConnectionError({ cause: response });
417
452
  }
418
453
 
454
+ const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${
455
+ response.ok ? 'succeeded' : 'failed'
456
+ } with status ${response.status} in ${headersTime - startTime}ms`;
457
+
419
458
  if (!response.ok) {
420
- if (retriesRemaining && this.shouldRetry(response)) {
459
+ const shouldRetry = await this.shouldRetry(response);
460
+ if (retriesRemaining && shouldRetry) {
421
461
  const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
422
- logger(this).debug(`response (error; ${retryMessage})`, response.status, url, response.headers);
423
- return this.retryRequest(options, retriesRemaining, response.headers);
462
+
463
+ // We don't need the body of this response.
464
+ await Shims.CancelReadableStream(response.body);
465
+ loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
466
+ loggerFor(this).debug(
467
+ `[${requestLogID}] response error (${retryMessage})`,
468
+ formatRequestDetails({
469
+ retryOfRequestLogID,
470
+ url: response.url,
471
+ status: response.status,
472
+ headers: response.headers,
473
+ durationMs: headersTime - startTime,
474
+ }),
475
+ );
476
+ return this.retryRequest(
477
+ options,
478
+ retriesRemaining,
479
+ retryOfRequestLogID ?? requestLogID,
480
+ response.headers,
481
+ );
424
482
  }
425
483
 
484
+ const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;
485
+
486
+ loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
487
+
426
488
  const errText = await response.text().catch((err: any) => castToError(err).message);
427
489
  const errJSON = safeJSON(errText);
428
490
  const errMessage = errJSON ? undefined : errText;
429
- const retryMessage = retriesRemaining ? `(error; no more retries left)` : `(error; not retryable)`;
430
491
 
431
- logger(this).debug(
432
- `response (error; ${retryMessage})`,
433
- response.status,
434
- url,
435
- response.headers,
436
- errMessage,
492
+ loggerFor(this).debug(
493
+ `[${requestLogID}] response error (${retryMessage})`,
494
+ formatRequestDetails({
495
+ retryOfRequestLogID,
496
+ url: response.url,
497
+ status: response.status,
498
+ headers: response.headers,
499
+ message: errMessage,
500
+ durationMs: Date.now() - startTime,
501
+ }),
437
502
  );
438
503
 
439
504
  const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
440
505
  throw err;
441
506
  }
442
507
 
443
- return { response, options, controller };
508
+ loggerFor(this).info(responseInfo);
509
+ loggerFor(this).debug(
510
+ `[${requestLogID}] response start`,
511
+ formatRequestDetails({
512
+ retryOfRequestLogID,
513
+ url: response.url,
514
+ status: response.status,
515
+ headers: response.headers,
516
+ durationMs: headersTime - startTime,
517
+ }),
518
+ );
519
+
520
+ return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
444
521
  }
445
522
 
446
523
  async fetchWithTimeout(
@@ -450,11 +527,14 @@ export class Roark {
450
527
  controller: AbortController,
451
528
  ): Promise<Response> {
452
529
  const { signal, method, ...options } = init || {};
453
- if (signal) signal.addEventListener('abort', () => controller.abort());
530
+ const abort = this._makeAbort(controller);
531
+ if (signal) signal.addEventListener('abort', abort, { once: true });
454
532
 
455
- const timeout = setTimeout(() => controller.abort(), ms);
533
+ const timeout = setTimeout(abort, ms);
456
534
 
457
- const isReadableBody = Shims.isReadableLike(options.body);
535
+ const isReadableBody =
536
+ ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) ||
537
+ (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body);
458
538
 
459
539
  const fetchOptions: RequestInit = {
460
540
  signal: controller.signal as any,
@@ -468,15 +548,15 @@ export class Roark {
468
548
  fetchOptions.method = method.toUpperCase();
469
549
  }
470
550
 
471
- return (
551
+ try {
472
552
  // use undefined this binding; fetch errors if bound to something else in browser/cloudflare
473
- this.fetch.call(undefined, url, fetchOptions).finally(() => {
474
- clearTimeout(timeout);
475
- })
476
- );
553
+ return await this.fetch.call(undefined, url, fetchOptions);
554
+ } finally {
555
+ clearTimeout(timeout);
556
+ }
477
557
  }
478
558
 
479
- private shouldRetry(response: Response): boolean {
559
+ private async shouldRetry(response: Response): Promise<boolean> {
480
560
  // Note this is not a standard header.
481
561
  const shouldRetryHeader = response.headers.get('x-should-retry');
482
562
 
@@ -502,6 +582,7 @@ export class Roark {
502
582
  private async retryRequest(
503
583
  options: FinalRequestOptions,
504
584
  retriesRemaining: number,
585
+ requestLogID: string,
505
586
  responseHeaders?: Headers | undefined,
506
587
  ): Promise<APIResponseProps> {
507
588
  let timeoutMillis: number | undefined;
@@ -534,7 +615,7 @@ export class Roark {
534
615
  }
535
616
  await sleep(timeoutMillis);
536
617
 
537
- return this.makeRequest(options, retriesRemaining - 1);
618
+ return this.makeRequest(options, retriesRemaining - 1, requestLogID);
538
619
  }
539
620
 
540
621
  private calculateDefaultRetryTimeoutMillis(retriesRemaining: number, maxRetries: number): number {
@@ -552,17 +633,18 @@ export class Roark {
552
633
  return sleepSeconds * jitter * 1000;
553
634
  }
554
635
 
555
- buildRequest(
556
- options: FinalRequestOptions,
636
+ async buildRequest(
637
+ inputOptions: FinalRequestOptions,
557
638
  { retryCount = 0 }: { retryCount?: number } = {},
558
- ): { req: FinalizedRequestInit; url: string; timeout: number } {
559
- const { method, path, query } = options;
639
+ ): Promise<{ req: FinalizedRequestInit; url: string; timeout: number }> {
640
+ const options = { ...inputOptions };
641
+ const { method, path, query, defaultBaseURL } = options;
560
642
 
561
- const url = this.buildURL(path!, query as Record<string, unknown>);
643
+ const url = this.buildURL(path!, query as Record<string, unknown>, defaultBaseURL);
562
644
  if ('timeout' in options) validatePositiveInteger('timeout', options.timeout);
563
- const timeout = options.timeout ?? this.timeout;
645
+ options.timeout = options.timeout ?? this.timeout;
564
646
  const { bodyHeaders, body } = this.buildBody({ options });
565
- const reqHeaders = this.buildHeaders({ options, method, bodyHeaders, retryCount });
647
+ const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });
566
648
 
567
649
  const req: FinalizedRequestInit = {
568
650
  method,
@@ -575,10 +657,10 @@ export class Roark {
575
657
  ...((options.fetchOptions as any) ?? {}),
576
658
  };
577
659
 
578
- return { req, url, timeout };
660
+ return { req, url, timeout: options.timeout };
579
661
  }
580
662
 
581
- private buildHeaders({
663
+ private async buildHeaders({
582
664
  options,
583
665
  method,
584
666
  bodyHeaders,
@@ -588,7 +670,7 @@ export class Roark {
588
670
  method: HTTPMethod;
589
671
  bodyHeaders: HeadersLike;
590
672
  retryCount: number;
591
- }): Headers {
673
+ }): Promise<Headers> {
592
674
  let idempotencyHeaders: HeadersLike = {};
593
675
  if (this.idempotencyHeader && method !== 'get') {
594
676
  if (!options.idempotencyKey) options.idempotencyKey = this.defaultIdempotencyKey();
@@ -601,9 +683,10 @@ export class Roark {
601
683
  Accept: 'application/json',
602
684
  'User-Agent': this.getUserAgent(),
603
685
  'X-Stainless-Retry-Count': String(retryCount),
686
+ ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),
604
687
  ...getPlatformHeaders(),
605
688
  },
606
- this.authHeaders(options),
689
+ await this.authHeaders(options),
607
690
  this._options.defaultHeaders,
608
691
  bodyHeaders,
609
692
  options.headers,
@@ -614,6 +697,12 @@ export class Roark {
614
697
  return headers.values;
615
698
  }
616
699
 
700
+ private _makeAbort(controller: AbortController) {
701
+ // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure
702
+ // would capture all request options, and cause a memory leak.
703
+ return () => controller.abort();
704
+ }
705
+
617
706
  private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): {
618
707
  bodyHeaders: HeadersLike;
619
708
  body: BodyInit | undefined;
@@ -631,7 +720,7 @@ export class Roark {
631
720
  // Preserve legacy string encoding behavior for now
632
721
  headers.values.has('content-type')) ||
633
722
  // `Blob` is superset of `File`
634
- body instanceof Blob ||
723
+ ((globalThis as any).Blob && body instanceof (globalThis as any).Blob) ||
635
724
  // `FormData` -> `multipart/form-data`
636
725
  body instanceof FormData ||
637
726
  // `URLSearchParams` -> `application/x-www-form-urlencoded`
@@ -678,6 +767,7 @@ export class Roark {
678
767
  simulation: API.Simulation = new API.Simulation(this);
679
768
  persona: API.Persona = new API.Persona(this);
680
769
  }
770
+
681
771
  Roark.Health = Health;
682
772
  Roark.Evaluation = Evaluation;
683
773
  Roark.Call = Call;
@@ -685,6 +775,7 @@ Roark.Metric = Metric;
685
775
  Roark.Integrations = Integrations;
686
776
  Roark.Simulation = Simulation;
687
777
  Roark.Persona = Persona;
778
+
688
779
  export declare namespace Roark {
689
780
  export type RequestOptions = Opts.RequestOptions;
690
781
 
@@ -0,0 +1,3 @@
1
+ # `core`
2
+
3
+ This directory holds public modules implementing non-resource-specific SDK functionality.
@@ -0,0 +1,92 @@
1
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ import { type Roark } from '../client';
4
+
5
+ import { type PromiseOrValue } from '../internal/types';
6
+ import { APIResponseProps, defaultParseResponse } from '../internal/parse';
7
+
8
+ /**
9
+ * A subclass of `Promise` providing additional helper methods
10
+ * for interacting with the SDK.
11
+ */
12
+ export class APIPromise<T> extends Promise<T> {
13
+ private parsedPromise: Promise<T> | undefined;
14
+ #client: Roark;
15
+
16
+ constructor(
17
+ client: Roark,
18
+ private responsePromise: Promise<APIResponseProps>,
19
+ private parseResponse: (
20
+ client: Roark,
21
+ props: APIResponseProps,
22
+ ) => PromiseOrValue<T> = defaultParseResponse,
23
+ ) {
24
+ super((resolve) => {
25
+ // this is maybe a bit weird but this has to be a no-op to not implicitly
26
+ // parse the response body; instead .then, .catch, .finally are overridden
27
+ // to parse the response
28
+ resolve(null as any);
29
+ });
30
+ this.#client = client;
31
+ }
32
+
33
+ _thenUnwrap<U>(transform: (data: T, props: APIResponseProps) => U): APIPromise<U> {
34
+ return new APIPromise(this.#client, this.responsePromise, async (client, props) =>
35
+ transform(await this.parseResponse(client, props), props),
36
+ );
37
+ }
38
+
39
+ /**
40
+ * Gets the raw `Response` instance instead of parsing the response
41
+ * data.
42
+ *
43
+ * If you want to parse the response body but still get the `Response`
44
+ * instance, you can use {@link withResponse()}.
45
+ *
46
+ * 👋 Getting the wrong TypeScript type for `Response`?
47
+ * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]`
48
+ * to your `tsconfig.json`.
49
+ */
50
+ asResponse(): Promise<Response> {
51
+ return this.responsePromise.then((p) => p.response);
52
+ }
53
+
54
+ /**
55
+ * Gets the parsed response data and the raw `Response` instance.
56
+ *
57
+ * If you just want to get the raw `Response` instance without parsing it,
58
+ * you can use {@link asResponse()}.
59
+ *
60
+ * 👋 Getting the wrong TypeScript type for `Response`?
61
+ * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]`
62
+ * to your `tsconfig.json`.
63
+ */
64
+ async withResponse(): Promise<{ data: T; response: Response }> {
65
+ const [data, response] = await Promise.all([this.parse(), this.asResponse()]);
66
+ return { data, response };
67
+ }
68
+
69
+ private parse(): Promise<T> {
70
+ if (!this.parsedPromise) {
71
+ this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.#client, data));
72
+ }
73
+ return this.parsedPromise;
74
+ }
75
+
76
+ override then<TResult1 = T, TResult2 = never>(
77
+ onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,
78
+ onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null,
79
+ ): Promise<TResult1 | TResult2> {
80
+ return this.parse().then(onfulfilled, onrejected);
81
+ }
82
+
83
+ override catch<TResult = never>(
84
+ onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null,
85
+ ): Promise<T | TResult> {
86
+ return this.parse().catch(onrejected);
87
+ }
88
+
89
+ override finally(onfinally?: (() => void) | undefined | null): Promise<T> {
90
+ return this.parse().finally(onfinally);
91
+ }
92
+ }