@roarkanalytics/sdk 2.21.1 → 2.21.2

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 +8 -0
  2. package/README.md +69 -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
@@ -1,11 +1,29 @@
1
1
  import { type RequestOptions } from './request-options';
2
2
  import type { FilePropertyBag, Fetch } from './builtin-types';
3
- import { isFsReadStreamLike, type FsReadStreamLike } from './shims';
4
3
  import type { Roark } from '../client';
5
- import './polyfill/file.node.js';
4
+ import { ReadableStreamFrom } from './shims';
6
5
 
7
- type BlobLikePart = string | ArrayBuffer | ArrayBufferView | BlobLike | DataView;
8
- type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | DataView;
6
+ export type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | DataView;
7
+ type FsReadStream = AsyncIterable<Uint8Array> & { path: string | { toString(): string } };
8
+
9
+ // https://github.com/oven-sh/bun/issues/5980
10
+ interface BunFile extends Blob {
11
+ readonly name?: string | undefined;
12
+ }
13
+
14
+ export const checkFileSupport = () => {
15
+ if (typeof File === 'undefined') {
16
+ const { process } = globalThis as any;
17
+ const isOldNode =
18
+ typeof process?.versions?.node === 'string' && parseInt(process.versions.node.split('.')) < 20;
19
+ throw new Error(
20
+ '`File` is not defined as a global, which is required for file uploads.' +
21
+ (isOldNode ?
22
+ " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`."
23
+ : ''),
24
+ );
25
+ }
26
+ };
9
27
 
10
28
  /**
11
29
  * Typically, this is a native "File" class.
@@ -16,188 +34,38 @@ type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | DataView;
16
34
  * For convenience, you can also pass a fetch Response, or in Node,
17
35
  * the result of fs.createReadStream().
18
36
  */
19
- export type Uploadable = FileLike | ResponseLike | FsReadStreamLike;
20
-
21
- /**
22
- * Intended to match DOM Blob, node-fetch Blob, node:buffer Blob, etc.
23
- * Don't add arrayBuffer here, node-fetch doesn't have it
24
- */
25
- interface BlobLike {
26
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/size) */
27
- readonly size: number;
28
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/type) */
29
- readonly type: string;
30
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/text) */
31
- text(): Promise<string>;
32
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice) */
33
- slice(start?: number, end?: number): BlobLike;
34
- }
35
-
36
- /**
37
- * This check adds the arrayBuffer() method type because it is available and used at runtime
38
- */
39
- const isBlobLike = (value: any): value is BlobLike & { arrayBuffer(): Promise<ArrayBuffer> } =>
40
- value != null &&
41
- typeof value === 'object' &&
42
- typeof value.size === 'number' &&
43
- typeof value.type === 'string' &&
44
- typeof value.text === 'function' &&
45
- typeof value.slice === 'function' &&
46
- typeof value.arrayBuffer === 'function';
47
-
48
- /**
49
- * Intended to match DOM File, node:buffer File, undici File, etc.
50
- */
51
- interface FileLike extends BlobLike {
52
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/lastModified) */
53
- readonly lastModified: number;
54
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/name) */
55
- readonly name: string;
56
- }
57
- declare var FileClass: {
58
- prototype: FileLike;
59
- new (fileBits: BlobPart[], fileName: string, options?: FilePropertyBag): FileLike;
60
- };
61
-
62
- /**
63
- * This check adds the arrayBuffer() method type because it is available and used at runtime
64
- */
65
- const isFileLike = (value: any): value is FileLike & { arrayBuffer(): Promise<ArrayBuffer> } =>
66
- value != null &&
67
- typeof value === 'object' &&
68
- typeof value.name === 'string' &&
69
- typeof value.lastModified === 'number' &&
70
- isBlobLike(value);
71
-
72
- /**
73
- * Intended to match DOM Response, node-fetch Response, undici Response, etc.
74
- */
75
- export interface ResponseLike {
76
- url: string;
77
- blob(): Promise<BlobLike>;
78
- }
79
-
80
- const isResponseLike = (value: any): value is ResponseLike =>
81
- value != null &&
82
- typeof value === 'object' &&
83
- typeof value.url === 'string' &&
84
- typeof value.blob === 'function';
85
-
86
- const isUploadable = (value: any): value is Uploadable => {
87
- return isFileLike(value) || isResponseLike(value) || isFsReadStreamLike(value);
88
- };
89
-
90
- type ToFileInput = Uploadable | Exclude<BlobLikePart, string> | AsyncIterable<BlobLikePart>;
37
+ export type Uploadable = File | Response | FsReadStream | BunFile;
91
38
 
92
39
  /**
93
40
  * Construct a `File` instance. This is used to ensure a helpful error is thrown
94
- * for environments that don't define a global `File` yet and so that we don't
95
- * accidentally rely on a global `File` type in our annotations.
41
+ * for environments that don't define a global `File` yet.
96
42
  */
97
- function makeFile(fileBits: BlobPart[], fileName: string, options?: FilePropertyBag): FileLike {
98
- const File = (globalThis as any).File as typeof FileClass | undefined;
99
- if (typeof File === 'undefined') {
100
- throw new Error('`File` is not defined as a global which is required for file uploads');
101
- }
102
-
103
- return new File(fileBits, fileName, options);
43
+ export function makeFile(
44
+ fileBits: BlobPart[],
45
+ fileName: string | undefined,
46
+ options?: FilePropertyBag,
47
+ ): File {
48
+ checkFileSupport();
49
+ return new File(fileBits as any, fileName ?? 'unknown_file', options);
104
50
  }
105
51
 
106
- /**
107
- * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats
108
- * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s
109
- * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible
110
- * @param {Object=} options additional properties
111
- * @param {string=} options.type the MIME type of the content
112
- * @param {number=} options.lastModified the last modified timestamp
113
- * @returns a {@link File} with the given properties
114
- */
115
- export async function toFile(
116
- value: ToFileInput | PromiseLike<ToFileInput>,
117
- name?: string | null | undefined,
118
- options?: FilePropertyBag | undefined,
119
- ): Promise<FileLike> {
120
- // If it's a promise, resolve it.
121
- value = await value;
122
-
123
- // If we've been given a `File` we don't need to do anything
124
- if (isFileLike(value)) {
125
- const File = (globalThis as any).File as typeof FileClass | undefined;
126
- if (File && value instanceof File) {
127
- return value;
128
- }
129
- return makeFile([await value.arrayBuffer()], value.name);
130
- }
131
-
132
- if (isResponseLike(value)) {
133
- const blob = await value.blob();
134
- name ||= new URL(value.url).pathname.split(/[\\/]/).pop() ?? 'unknown_file';
135
-
136
- return makeFile(await getBytes(blob), name, options);
137
- }
138
-
139
- const parts = await getBytes(value);
140
-
141
- name ||= getName(value) ?? 'unknown_file';
142
-
143
- if (!options?.type) {
144
- const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type);
145
- if (typeof type === 'string') {
146
- options = { ...options, type };
147
- }
148
- }
149
-
150
- return makeFile(parts, name, options);
151
- }
152
-
153
- export async function getBytes(
154
- value: Uploadable | BlobLikePart | AsyncIterable<BlobLikePart>,
155
- ): Promise<Array<BlobPart>> {
156
- let parts: Array<BlobPart> = [];
157
- if (
158
- typeof value === 'string' ||
159
- ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc.
160
- value instanceof ArrayBuffer
161
- ) {
162
- parts.push(value);
163
- } else if (isBlobLike(value)) {
164
- parts.push(value instanceof Blob ? value : await value.arrayBuffer());
165
- } else if (
166
- isAsyncIterableIterator(value) // includes Readable, ReadableStream, etc.
167
- ) {
168
- for await (const chunk of value) {
169
- parts.push(...(await getBytes(chunk as BlobLikePart))); // TODO, consider validating?
170
- }
171
- } else {
172
- const constructor = value?.constructor?.name;
173
- throw new Error(
174
- `Unexpected data type: ${typeof value}${
175
- constructor ? `; constructor: ${constructor}` : ''
176
- }${propsForError(value)}`,
177
- );
178
- }
179
-
180
- return parts;
181
- }
182
-
183
- function propsForError(value: unknown): string {
184
- if (typeof value !== 'object' || value === null) return '';
185
- const props = Object.getOwnPropertyNames(value);
186
- return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`;
187
- }
188
-
189
- function getName(value: unknown): string | undefined {
52
+ export function getName(value: any): string | undefined {
190
53
  return (
191
- (typeof value === 'object' &&
192
- value !== null &&
193
- (('name' in value && String(value.name)) ||
194
- ('filename' in value && String(value.filename)) ||
195
- ('path' in value && String(value.path).split(/[\\/]/).pop()))) ||
196
- undefined
54
+ (
55
+ (typeof value === 'object' &&
56
+ value !== null &&
57
+ (('name' in value && value.name && String(value.name)) ||
58
+ ('url' in value && value.url && String(value.url)) ||
59
+ ('filename' in value && value.filename && String(value.filename)) ||
60
+ ('path' in value && value.path && String(value.path)))) ||
61
+ ''
62
+ )
63
+ .split(/[\\/]/)
64
+ .pop() || undefined
197
65
  );
198
66
  }
199
67
 
200
- const isAsyncIterableIterator = (value: any): value is AsyncIterableIterator<unknown> =>
68
+ export const isAsyncIterable = (value: any): value is AsyncIterable<any> =>
201
69
  value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function';
202
70
 
203
71
  /**
@@ -222,7 +90,7 @@ export const multipartFormRequestOptions = async (
222
90
  return { ...opts, body: await createForm(opts.body, fetch) };
223
91
  };
224
92
 
225
- const supportsFormDataMap = new WeakMap<Fetch, Promise<boolean>>();
93
+ const supportsFormDataMap = /* @__PURE__ */ new WeakMap<Fetch, Promise<boolean>>();
226
94
 
227
95
  /**
228
96
  * node-fetch doesn't support the global FormData object in recent node versions. Instead of sending
@@ -268,6 +136,15 @@ export const createForm = async <T = Record<string, unknown>>(
268
136
  return form;
269
137
  };
270
138
 
139
+ // We check for Blob not File because Bun.File doesn't inherit from File,
140
+ // but they both inherit from Blob and have a `name` property at runtime.
141
+ const isNamedBlob = (value: unknown) => value instanceof Blob && 'name' in value;
142
+
143
+ const isUploadable = (value: unknown) =>
144
+ typeof value === 'object' &&
145
+ value !== null &&
146
+ (value instanceof Response || isAsyncIterable(value) || isNamedBlob(value));
147
+
271
148
  const hasUploadableValue = (value: unknown): boolean => {
272
149
  if (isUploadable(value)) return true;
273
150
  if (Array.isArray(value)) return value.some(hasUploadableValue);
@@ -290,9 +167,12 @@ const addFormValue = async (form: FormData, key: string, value: unknown): Promis
290
167
  // TODO: make nested formats configurable
291
168
  if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
292
169
  form.append(key, String(value));
293
- } else if (isUploadable(value)) {
294
- const file = await toFile(value);
295
- form.append(key, file as any);
170
+ } else if (value instanceof Response) {
171
+ form.append(key, makeFile([await value.blob()], getName(value)));
172
+ } else if (isAsyncIterable(value)) {
173
+ form.append(key, makeFile([await new Response(ReadableStreamFrom(value)).blob()], getName(value)));
174
+ } else if (isNamedBlob(value)) {
175
+ form.append(key, value, getName(value));
296
176
  } else if (Array.isArray(value)) {
297
177
  await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry)));
298
178
  } else if (typeof value === 'object') {
@@ -1,18 +1,19 @@
1
1
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
- import { RoarkError } from '../../error';
3
+ import { RoarkError } from '../../core/error';
4
+ import { encodeUTF8 } from './bytes';
4
5
 
5
6
  export const toBase64 = (data: string | Uint8Array | null | undefined): string => {
6
7
  if (!data) return '';
7
8
 
8
- if (typeof data === 'string') {
9
- data = new (globalThis as any).TextEncoder().encode(data);
10
- }
11
-
12
9
  if (typeof (globalThis as any).Buffer !== 'undefined') {
13
10
  return (globalThis as any).Buffer.from(data).toString('base64');
14
11
  }
15
12
 
13
+ if (typeof data === 'string') {
14
+ data = encodeUTF8(data);
15
+ }
16
+
16
17
  if (typeof btoa !== 'undefined') {
17
18
  return btoa(String.fromCharCode.apply(null, data as any));
18
19
  }
@@ -22,15 +23,17 @@ export const toBase64 = (data: string | Uint8Array | null | undefined): string =
22
23
 
23
24
  export const fromBase64 = (str: string): Uint8Array => {
24
25
  if (typeof (globalThis as any).Buffer !== 'undefined') {
25
- return new Uint8Array((globalThis as any).Buffer.from(str, 'base64'));
26
+ const buf = (globalThis as any).Buffer.from(str, 'base64');
27
+ return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
26
28
  }
27
29
 
28
30
  if (typeof atob !== 'undefined') {
29
- return new Uint8Array(
30
- atob(str)
31
- .split('')
32
- .map((c) => c.charCodeAt(0)),
33
- );
31
+ const bstr = atob(str);
32
+ const buf = new Uint8Array(bstr.length);
33
+ for (let i = 0; i < bstr.length; i++) {
34
+ buf[i] = bstr.charCodeAt(i);
35
+ }
36
+ return buf;
34
37
  }
35
38
 
36
39
  throw new RoarkError('Cannot decode base64 string; Expected `Buffer` or `atob` to be defined');
@@ -0,0 +1,32 @@
1
+ export function concatBytes(buffers: Uint8Array[]): Uint8Array {
2
+ let length = 0;
3
+ for (const buffer of buffers) {
4
+ length += buffer.length;
5
+ }
6
+ const output = new Uint8Array(length);
7
+ let index = 0;
8
+ for (const buffer of buffers) {
9
+ output.set(buffer, index);
10
+ index += buffer.length;
11
+ }
12
+
13
+ return output;
14
+ }
15
+
16
+ let encodeUTF8_: (str: string) => Uint8Array;
17
+ export function encodeUTF8(str: string) {
18
+ let encoder;
19
+ return (
20
+ encodeUTF8_ ??
21
+ ((encoder = new (globalThis as any).TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder)))
22
+ )(str);
23
+ }
24
+
25
+ let decodeUTF8_: (bytes: Uint8Array) => string;
26
+ export function decodeUTF8(bytes: Uint8Array) {
27
+ let decoder;
28
+ return (
29
+ decodeUTF8_ ??
30
+ ((decoder = new (globalThis as any).TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder)))
31
+ )(bytes);
32
+ }
@@ -1,7 +1,17 @@
1
1
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
- import type { LogLevel, Logger } from '../../client';
3
+ import { hasOwn } from './values';
4
4
  import { type Roark } from '../../client';
5
+ import { RequestOptions } from '../request-options';
6
+
7
+ type LogFn = (message: string, ...rest: unknown[]) => void;
8
+ export type Logger = {
9
+ error: LogFn;
10
+ warn: LogFn;
11
+ info: LogFn;
12
+ debug: LogFn;
13
+ };
14
+ export type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug';
5
15
 
6
16
  const levelNumbers = {
7
17
  off: 0,
@@ -11,39 +21,106 @@ const levelNumbers = {
11
21
  debug: 500,
12
22
  };
13
23
 
24
+ export const parseLogLevel = (
25
+ maybeLevel: string | undefined,
26
+ sourceName: string,
27
+ client: Roark,
28
+ ): LogLevel | undefined => {
29
+ if (!maybeLevel) {
30
+ return undefined;
31
+ }
32
+ if (hasOwn(levelNumbers, maybeLevel)) {
33
+ return maybeLevel;
34
+ }
35
+ loggerFor(client).warn(
36
+ `${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(
37
+ Object.keys(levelNumbers),
38
+ )}`,
39
+ );
40
+ return undefined;
41
+ };
42
+
14
43
  function noop() {}
15
44
 
16
- function logFn(logger: Logger | undefined, clientLevel: LogLevel | undefined, level: keyof Logger) {
17
- if (!logger || levelNumbers[level] > levelNumbers[clientLevel!]!) {
45
+ function makeLogFn(fnLevel: keyof Logger, logger: Logger | undefined, logLevel: LogLevel) {
46
+ if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) {
18
47
  return noop;
19
48
  } else {
20
49
  // Don't wrap logger functions, we want the stacktrace intact!
21
- return logger[level].bind(logger);
50
+ return logger[fnLevel].bind(logger);
22
51
  }
23
52
  }
24
53
 
25
- let lastLogger: { deref(): Logger } | undefined;
26
- let lastLevel: LogLevel | undefined;
27
- let lastLevelLogger: Logger;
54
+ const noopLogger = {
55
+ error: noop,
56
+ warn: noop,
57
+ info: noop,
58
+ debug: noop,
59
+ };
60
+
61
+ let cachedLoggers = /* @__PURE__ */ new WeakMap<Logger, [LogLevel, Logger]>();
62
+
63
+ export function loggerFor(client: Roark): Logger {
64
+ const logger = client.logger;
65
+ const logLevel = client.logLevel ?? 'off';
66
+ if (!logger) {
67
+ return noopLogger;
68
+ }
28
69
 
29
- export function logger(client: Roark): Logger {
30
- let { logger, logLevel: clientLevel } = client;
31
- if (lastLevel === clientLevel && (logger === lastLogger || logger === lastLogger?.deref())) {
32
- return lastLevelLogger;
70
+ const cachedLogger = cachedLoggers.get(logger);
71
+ if (cachedLogger && cachedLogger[0] === logLevel) {
72
+ return cachedLogger[1];
33
73
  }
74
+
34
75
  const levelLogger = {
35
- error: logFn(logger, clientLevel, 'error'),
36
- warn: logFn(logger, clientLevel, 'warn'),
37
- info: logFn(logger, clientLevel, 'info'),
38
- debug: logFn(logger, clientLevel, 'debug'),
76
+ error: makeLogFn('error', logger, logLevel),
77
+ warn: makeLogFn('warn', logger, logLevel),
78
+ info: makeLogFn('info', logger, logLevel),
79
+ debug: makeLogFn('debug', logger, logLevel),
39
80
  };
40
- const { WeakRef } = globalThis as any;
41
- lastLogger =
42
- logger ?
43
- WeakRef ? new WeakRef(logger)
44
- : { deref: () => logger }
45
- : undefined;
46
- lastLevel = clientLevel;
47
- lastLevelLogger = levelLogger;
81
+
82
+ cachedLoggers.set(logger, [logLevel, levelLogger]);
83
+
48
84
  return levelLogger;
49
85
  }
86
+
87
+ export const formatRequestDetails = (details: {
88
+ options?: RequestOptions | undefined;
89
+ headers?: Headers | Record<string, string> | undefined;
90
+ retryOfRequestLogID?: string | undefined;
91
+ retryOf?: string | undefined;
92
+ url?: string | undefined;
93
+ status?: number | undefined;
94
+ method?: string | undefined;
95
+ durationMs?: number | undefined;
96
+ message?: unknown;
97
+ body?: unknown;
98
+ }) => {
99
+ if (details.options) {
100
+ details.options = { ...details.options };
101
+ delete details.options['headers']; // redundant + leaks internals
102
+ }
103
+ if (details.headers) {
104
+ details.headers = Object.fromEntries(
105
+ (details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(
106
+ ([name, value]) => [
107
+ name,
108
+ (
109
+ name.toLowerCase() === 'authorization' ||
110
+ name.toLowerCase() === 'cookie' ||
111
+ name.toLowerCase() === 'set-cookie'
112
+ ) ?
113
+ '***'
114
+ : value,
115
+ ],
116
+ ),
117
+ );
118
+ }
119
+ if ('retryOfRequestLogID' in details) {
120
+ if (details.retryOfRequestLogID) {
121
+ details.retryOf = details.retryOfRequestLogID;
122
+ }
123
+ delete details.retryOfRequestLogID;
124
+ }
125
+ return details;
126
+ };
@@ -0,0 +1,88 @@
1
+ import { RoarkError } from '../../core/error';
2
+
3
+ /**
4
+ * Percent-encode everything that isn't safe to have in a path without encoding safe chars.
5
+ *
6
+ * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3:
7
+ * > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
8
+ * > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
9
+ * > pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
10
+ */
11
+ export function encodeURIPath(str: string) {
12
+ return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
13
+ }
14
+
15
+ const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
16
+
17
+ export const createPathTagFunction = (pathEncoder = encodeURIPath) =>
18
+ function path(statics: readonly string[], ...params: readonly unknown[]): string {
19
+ // If there are no params, no processing is needed.
20
+ if (statics.length === 1) return statics[0]!;
21
+
22
+ let postPath = false;
23
+ const invalidSegments = [];
24
+ const path = statics.reduce((previousValue, currentValue, index) => {
25
+ if (/[?#]/.test(currentValue)) {
26
+ postPath = true;
27
+ }
28
+ const value = params[index];
29
+ let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value);
30
+ if (
31
+ index !== params.length &&
32
+ (value == null ||
33
+ (typeof value === 'object' &&
34
+ // handle values from other realms
35
+ value.toString ===
36
+ Object.getPrototypeOf(Object.getPrototypeOf((value as any).hasOwnProperty ?? EMPTY) ?? EMPTY)
37
+ ?.toString))
38
+ ) {
39
+ encoded = value + '';
40
+ invalidSegments.push({
41
+ start: previousValue.length + currentValue.length,
42
+ length: encoded.length,
43
+ error: `Value of type ${Object.prototype.toString
44
+ .call(value)
45
+ .slice(8, -1)} is not a valid path parameter`,
46
+ });
47
+ }
48
+ return previousValue + currentValue + (index === params.length ? '' : encoded);
49
+ }, '');
50
+
51
+ const pathOnly = path.split(/[?#]/, 1)[0]!;
52
+ const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
53
+ let match;
54
+
55
+ // Find all invalid segments
56
+ while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
57
+ invalidSegments.push({
58
+ start: match.index,
59
+ length: match[0].length,
60
+ error: `Value "${match[0]}" can\'t be safely passed as a path parameter`,
61
+ });
62
+ }
63
+
64
+ invalidSegments.sort((a, b) => a.start - b.start);
65
+
66
+ if (invalidSegments.length > 0) {
67
+ let lastEnd = 0;
68
+ const underline = invalidSegments.reduce((acc, segment) => {
69
+ const spaces = ' '.repeat(segment.start - lastEnd);
70
+ const arrows = '^'.repeat(segment.length);
71
+ lastEnd = segment.start + segment.length;
72
+ return acc + spaces + arrows;
73
+ }, '');
74
+
75
+ throw new RoarkError(
76
+ `Path parameters result in path with invalid segments:\n${invalidSegments
77
+ .map((e) => e.error)
78
+ .join('\n')}\n${path}\n${underline}`,
79
+ );
80
+ }
81
+
82
+ return path;
83
+ };
84
+
85
+ /**
86
+ * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced.
87
+ */
88
+ export const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
@@ -1,13 +1,17 @@
1
1
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
- import { crypto } from '../polyfill/crypto.node';
4
-
5
3
  /**
6
4
  * https://stackoverflow.com/a/2117523
7
5
  */
8
- export function uuid4() {
9
- if (crypto.randomUUID) return crypto.randomUUID();
6
+ export let uuid4 = function () {
7
+ const { crypto } = globalThis as any;
8
+ if (crypto?.randomUUID) {
9
+ uuid4 = crypto.randomUUID.bind(crypto);
10
+ return crypto.randomUUID();
11
+ }
12
+ const u8 = new Uint8Array(1);
13
+ const randomByte = crypto ? () => crypto.getRandomValues(u8)[0]! : () => (Math.random() * 0xff) & 0xff;
10
14
  return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) =>
11
- (+c ^ (crypto.getRandomValues(new Uint8Array(1))[0]! & (15 >> (+c / 4)))).toString(16),
15
+ (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16),
12
16
  );
13
- }
17
+ };