@expandai/sdk 0.16.0 → 0.17.1

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 (360) hide show
  1. package/LICENSE +2 -1
  2. package/README.md +83 -307
  3. package/build/dts/Client.d.ts +61 -0
  4. package/build/dts/Client.d.ts.map +1 -0
  5. package/build/dts/Error.d.ts +90 -0
  6. package/build/dts/Error.d.ts.map +1 -0
  7. package/build/dts/FetchJson.d.ts +364 -0
  8. package/build/dts/FetchJson.d.ts.map +1 -0
  9. package/build/dts/Generated.d.ts +1863 -0
  10. package/build/dts/Generated.d.ts.map +1 -0
  11. package/build/dts/HttpClientHelpers.d.ts +5 -0
  12. package/build/dts/HttpClientHelpers.d.ts.map +1 -0
  13. package/build/dts/Internal.d.ts +49 -0
  14. package/build/dts/Internal.d.ts.map +1 -0
  15. package/build/dts/Playground.d.ts +24 -0
  16. package/build/dts/Playground.d.ts.map +1 -0
  17. package/build/dts/Service.d.ts +277 -0
  18. package/build/dts/Service.d.ts.map +1 -0
  19. package/build/dts/index.d.ts +6 -0
  20. package/build/dts/index.d.ts.map +1 -0
  21. package/build/esm/Client.js +87 -0
  22. package/build/esm/Client.js.map +1 -0
  23. package/build/esm/Error.js +91 -0
  24. package/build/esm/Error.js.map +1 -0
  25. package/build/esm/FetchJson.js +70 -0
  26. package/build/esm/FetchJson.js.map +1 -0
  27. package/build/esm/Generated.js +646 -0
  28. package/build/esm/Generated.js.map +1 -0
  29. package/build/esm/HttpClientHelpers.js +14 -0
  30. package/build/esm/HttpClientHelpers.js.map +1 -0
  31. package/build/esm/Internal.js +95 -0
  32. package/build/esm/Internal.js.map +1 -0
  33. package/build/esm/Playground.js +55 -0
  34. package/build/esm/Playground.js.map +1 -0
  35. package/build/esm/Service.js +174 -0
  36. package/build/esm/Service.js.map +1 -0
  37. package/build/esm/index.js +4 -0
  38. package/build/esm/index.js.map +1 -0
  39. package/package.json +53 -136
  40. package/src/Client.ts +128 -0
  41. package/src/Error.ts +105 -0
  42. package/src/FetchJson.ts +109 -0
  43. package/src/Generated.ts +949 -0
  44. package/src/HttpClientHelpers.ts +24 -0
  45. package/src/Internal.ts +246 -0
  46. package/src/Playground.ts +76 -0
  47. package/src/Service.ts +264 -0
  48. package/src/index.ts +27 -21
  49. package/CHANGELOG.md +0 -224
  50. package/api-promise.d.mts +0 -2
  51. package/api-promise.d.mts.map +0 -1
  52. package/api-promise.d.ts +0 -2
  53. package/api-promise.d.ts.map +0 -1
  54. package/api-promise.js +0 -6
  55. package/api-promise.js.map +0 -1
  56. package/api-promise.mjs +0 -2
  57. package/api-promise.mjs.map +0 -1
  58. package/client.d.mts +0 -184
  59. package/client.d.mts.map +0 -1
  60. package/client.d.ts +0 -184
  61. package/client.d.ts.map +0 -1
  62. package/client.js +0 -476
  63. package/client.js.map +0 -1
  64. package/client.mjs +0 -472
  65. package/client.mjs.map +0 -1
  66. package/core/api-promise.d.mts +0 -46
  67. package/core/api-promise.d.mts.map +0 -1
  68. package/core/api-promise.d.ts +0 -46
  69. package/core/api-promise.d.ts.map +0 -1
  70. package/core/api-promise.js +0 -74
  71. package/core/api-promise.js.map +0 -1
  72. package/core/api-promise.mjs +0 -70
  73. package/core/api-promise.mjs.map +0 -1
  74. package/core/error.d.mts +0 -46
  75. package/core/error.d.mts.map +0 -1
  76. package/core/error.d.ts +0 -46
  77. package/core/error.d.ts.map +0 -1
  78. package/core/error.js +0 -113
  79. package/core/error.js.map +0 -1
  80. package/core/error.mjs +0 -97
  81. package/core/error.mjs.map +0 -1
  82. package/core/resource.d.mts +0 -6
  83. package/core/resource.d.mts.map +0 -1
  84. package/core/resource.d.ts +0 -6
  85. package/core/resource.d.ts.map +0 -1
  86. package/core/resource.js +0 -11
  87. package/core/resource.js.map +0 -1
  88. package/core/resource.mjs +0 -7
  89. package/core/resource.mjs.map +0 -1
  90. package/core/uploads.d.mts +0 -3
  91. package/core/uploads.d.mts.map +0 -1
  92. package/core/uploads.d.ts +0 -3
  93. package/core/uploads.d.ts.map +0 -1
  94. package/core/uploads.js +0 -6
  95. package/core/uploads.js.map +0 -1
  96. package/core/uploads.mjs +0 -2
  97. package/core/uploads.mjs.map +0 -1
  98. package/error.d.mts +0 -2
  99. package/error.d.mts.map +0 -1
  100. package/error.d.ts +0 -2
  101. package/error.d.ts.map +0 -1
  102. package/error.js +0 -6
  103. package/error.js.map +0 -1
  104. package/error.mjs +0 -2
  105. package/error.mjs.map +0 -1
  106. package/index.d.mts +0 -6
  107. package/index.d.mts.map +0 -1
  108. package/index.d.ts +0 -6
  109. package/index.d.ts.map +0 -1
  110. package/index.js +0 -30
  111. package/index.js.map +0 -1
  112. package/index.mjs +0 -7
  113. package/index.mjs.map +0 -1
  114. package/internal/builtin-types.d.mts +0 -73
  115. package/internal/builtin-types.d.mts.map +0 -1
  116. package/internal/builtin-types.d.ts +0 -73
  117. package/internal/builtin-types.d.ts.map +0 -1
  118. package/internal/builtin-types.js +0 -4
  119. package/internal/builtin-types.js.map +0 -1
  120. package/internal/builtin-types.mjs +0 -3
  121. package/internal/builtin-types.mjs.map +0 -1
  122. package/internal/detect-platform.d.mts +0 -15
  123. package/internal/detect-platform.d.mts.map +0 -1
  124. package/internal/detect-platform.d.ts +0 -15
  125. package/internal/detect-platform.d.ts.map +0 -1
  126. package/internal/detect-platform.js +0 -162
  127. package/internal/detect-platform.js.map +0 -1
  128. package/internal/detect-platform.mjs +0 -157
  129. package/internal/detect-platform.mjs.map +0 -1
  130. package/internal/errors.d.mts +0 -3
  131. package/internal/errors.d.mts.map +0 -1
  132. package/internal/errors.d.ts +0 -3
  133. package/internal/errors.d.ts.map +0 -1
  134. package/internal/errors.js +0 -41
  135. package/internal/errors.js.map +0 -1
  136. package/internal/errors.mjs +0 -36
  137. package/internal/errors.mjs.map +0 -1
  138. package/internal/headers.d.mts +0 -20
  139. package/internal/headers.d.mts.map +0 -1
  140. package/internal/headers.d.ts +0 -20
  141. package/internal/headers.d.ts.map +0 -1
  142. package/internal/headers.js +0 -79
  143. package/internal/headers.js.map +0 -1
  144. package/internal/headers.mjs +0 -74
  145. package/internal/headers.mjs.map +0 -1
  146. package/internal/parse.d.mts +0 -12
  147. package/internal/parse.d.mts.map +0 -1
  148. package/internal/parse.d.ts +0 -12
  149. package/internal/parse.d.ts.map +0 -1
  150. package/internal/parse.js +0 -40
  151. package/internal/parse.js.map +0 -1
  152. package/internal/parse.mjs +0 -37
  153. package/internal/parse.mjs.map +0 -1
  154. package/internal/request-options.d.mts +0 -75
  155. package/internal/request-options.d.mts.map +0 -1
  156. package/internal/request-options.d.ts +0 -75
  157. package/internal/request-options.d.ts.map +0 -1
  158. package/internal/request-options.js +0 -14
  159. package/internal/request-options.js.map +0 -1
  160. package/internal/request-options.mjs +0 -10
  161. package/internal/request-options.mjs.map +0 -1
  162. package/internal/shim-types.d.mts +0 -17
  163. package/internal/shim-types.d.mts.map +0 -1
  164. package/internal/shim-types.d.ts +0 -17
  165. package/internal/shim-types.d.ts.map +0 -1
  166. package/internal/shim-types.js +0 -4
  167. package/internal/shim-types.js.map +0 -1
  168. package/internal/shim-types.mjs +0 -3
  169. package/internal/shim-types.mjs.map +0 -1
  170. package/internal/shims.d.mts +0 -20
  171. package/internal/shims.d.mts.map +0 -1
  172. package/internal/shims.d.ts +0 -20
  173. package/internal/shims.d.ts.map +0 -1
  174. package/internal/shims.js +0 -92
  175. package/internal/shims.js.map +0 -1
  176. package/internal/shims.mjs +0 -85
  177. package/internal/shims.mjs.map +0 -1
  178. package/internal/to-file.d.mts +0 -45
  179. package/internal/to-file.d.mts.map +0 -1
  180. package/internal/to-file.d.ts +0 -45
  181. package/internal/to-file.d.ts.map +0 -1
  182. package/internal/to-file.js +0 -91
  183. package/internal/to-file.js.map +0 -1
  184. package/internal/to-file.mjs +0 -88
  185. package/internal/to-file.mjs.map +0 -1
  186. package/internal/tslib.js +0 -81
  187. package/internal/tslib.mjs +0 -17
  188. package/internal/types.d.mts +0 -69
  189. package/internal/types.d.mts.map +0 -1
  190. package/internal/types.d.ts +0 -69
  191. package/internal/types.d.ts.map +0 -1
  192. package/internal/types.js +0 -4
  193. package/internal/types.js.map +0 -1
  194. package/internal/types.mjs +0 -3
  195. package/internal/types.mjs.map +0 -1
  196. package/internal/uploads.d.mts +0 -42
  197. package/internal/uploads.d.mts.map +0 -1
  198. package/internal/uploads.d.ts +0 -42
  199. package/internal/uploads.d.ts.map +0 -1
  200. package/internal/uploads.js +0 -141
  201. package/internal/uploads.js.map +0 -1
  202. package/internal/uploads.mjs +0 -131
  203. package/internal/uploads.mjs.map +0 -1
  204. package/internal/utils/base64.d.mts +0 -3
  205. package/internal/utils/base64.d.mts.map +0 -1
  206. package/internal/utils/base64.d.ts +0 -3
  207. package/internal/utils/base64.d.ts.map +0 -1
  208. package/internal/utils/base64.js +0 -38
  209. package/internal/utils/base64.js.map +0 -1
  210. package/internal/utils/base64.mjs +0 -33
  211. package/internal/utils/base64.mjs.map +0 -1
  212. package/internal/utils/bytes.d.mts +0 -4
  213. package/internal/utils/bytes.d.mts.map +0 -1
  214. package/internal/utils/bytes.d.ts +0 -4
  215. package/internal/utils/bytes.d.ts.map +0 -1
  216. package/internal/utils/bytes.js +0 -31
  217. package/internal/utils/bytes.js.map +0 -1
  218. package/internal/utils/bytes.mjs +0 -26
  219. package/internal/utils/bytes.mjs.map +0 -1
  220. package/internal/utils/env.d.mts +0 -9
  221. package/internal/utils/env.d.mts.map +0 -1
  222. package/internal/utils/env.d.ts +0 -9
  223. package/internal/utils/env.d.ts.map +0 -1
  224. package/internal/utils/env.js +0 -22
  225. package/internal/utils/env.js.map +0 -1
  226. package/internal/utils/env.mjs +0 -18
  227. package/internal/utils/env.mjs.map +0 -1
  228. package/internal/utils/log.d.mts +0 -37
  229. package/internal/utils/log.d.mts.map +0 -1
  230. package/internal/utils/log.d.ts +0 -37
  231. package/internal/utils/log.d.ts.map +0 -1
  232. package/internal/utils/log.js +0 -86
  233. package/internal/utils/log.js.map +0 -1
  234. package/internal/utils/log.mjs +0 -80
  235. package/internal/utils/log.mjs.map +0 -1
  236. package/internal/utils/path.d.mts +0 -15
  237. package/internal/utils/path.d.mts.map +0 -1
  238. package/internal/utils/path.d.ts +0 -15
  239. package/internal/utils/path.d.ts.map +0 -1
  240. package/internal/utils/path.js +0 -79
  241. package/internal/utils/path.js.map +0 -1
  242. package/internal/utils/path.mjs +0 -74
  243. package/internal/utils/path.mjs.map +0 -1
  244. package/internal/utils/sleep.d.mts +0 -2
  245. package/internal/utils/sleep.d.mts.map +0 -1
  246. package/internal/utils/sleep.d.ts +0 -2
  247. package/internal/utils/sleep.d.ts.map +0 -1
  248. package/internal/utils/sleep.js +0 -7
  249. package/internal/utils/sleep.js.map +0 -1
  250. package/internal/utils/sleep.mjs +0 -3
  251. package/internal/utils/sleep.mjs.map +0 -1
  252. package/internal/utils/uuid.d.mts +0 -5
  253. package/internal/utils/uuid.d.mts.map +0 -1
  254. package/internal/utils/uuid.d.ts +0 -5
  255. package/internal/utils/uuid.d.ts.map +0 -1
  256. package/internal/utils/uuid.js +0 -19
  257. package/internal/utils/uuid.js.map +0 -1
  258. package/internal/utils/uuid.mjs +0 -15
  259. package/internal/utils/uuid.mjs.map +0 -1
  260. package/internal/utils/values.d.mts +0 -18
  261. package/internal/utils/values.d.mts.map +0 -1
  262. package/internal/utils/values.d.ts +0 -18
  263. package/internal/utils/values.d.ts.map +0 -1
  264. package/internal/utils/values.js +0 -112
  265. package/internal/utils/values.js.map +0 -1
  266. package/internal/utils/values.mjs +0 -94
  267. package/internal/utils/values.mjs.map +0 -1
  268. package/internal/utils.d.mts +0 -7
  269. package/internal/utils.d.mts.map +0 -1
  270. package/internal/utils.d.ts +0 -7
  271. package/internal/utils.d.ts.map +0 -1
  272. package/internal/utils.js +0 -11
  273. package/internal/utils.js.map +0 -1
  274. package/internal/utils.mjs +0 -8
  275. package/internal/utils.mjs.map +0 -1
  276. package/resource.d.mts +0 -2
  277. package/resource.d.mts.map +0 -1
  278. package/resource.d.ts +0 -2
  279. package/resource.d.ts.map +0 -1
  280. package/resource.js +0 -6
  281. package/resource.js.map +0 -1
  282. package/resource.mjs +0 -2
  283. package/resource.mjs.map +0 -1
  284. package/resources/index.d.mts +0 -2
  285. package/resources/index.d.mts.map +0 -1
  286. package/resources/index.d.ts +0 -2
  287. package/resources/index.d.ts.map +0 -1
  288. package/resources/index.js +0 -4
  289. package/resources/index.js.map +0 -1
  290. package/resources/index.mjs +0 -3
  291. package/resources/index.mjs.map +0 -1
  292. package/resources/top-level.d.mts +0 -468
  293. package/resources/top-level.d.mts.map +0 -1
  294. package/resources/top-level.d.ts +0 -468
  295. package/resources/top-level.d.ts.map +0 -1
  296. package/resources/top-level.js +0 -4
  297. package/resources/top-level.js.map +0 -1
  298. package/resources/top-level.mjs +0 -3
  299. package/resources/top-level.mjs.map +0 -1
  300. package/resources.d.mts +0 -2
  301. package/resources.d.mts.map +0 -1
  302. package/resources.d.ts +0 -2
  303. package/resources.d.ts.map +0 -1
  304. package/resources.js +0 -5
  305. package/resources.js.map +0 -1
  306. package/resources.mjs +0 -2
  307. package/resources.mjs.map +0 -1
  308. package/src/api-promise.ts +0 -2
  309. package/src/client.ts +0 -744
  310. package/src/core/README.md +0 -3
  311. package/src/core/api-promise.ts +0 -92
  312. package/src/core/error.ts +0 -130
  313. package/src/core/resource.ts +0 -11
  314. package/src/core/uploads.ts +0 -2
  315. package/src/error.ts +0 -2
  316. package/src/internal/README.md +0 -3
  317. package/src/internal/builtin-types.ts +0 -93
  318. package/src/internal/detect-platform.ts +0 -196
  319. package/src/internal/errors.ts +0 -33
  320. package/src/internal/headers.ts +0 -97
  321. package/src/internal/parse.ts +0 -56
  322. package/src/internal/request-options.ts +0 -91
  323. package/src/internal/shim-types.ts +0 -26
  324. package/src/internal/shims.ts +0 -107
  325. package/src/internal/to-file.ts +0 -154
  326. package/src/internal/types.ts +0 -95
  327. package/src/internal/uploads.ts +0 -187
  328. package/src/internal/utils/base64.ts +0 -40
  329. package/src/internal/utils/bytes.ts +0 -32
  330. package/src/internal/utils/env.ts +0 -18
  331. package/src/internal/utils/log.ts +0 -127
  332. package/src/internal/utils/path.ts +0 -88
  333. package/src/internal/utils/sleep.ts +0 -3
  334. package/src/internal/utils/uuid.ts +0 -17
  335. package/src/internal/utils/values.ts +0 -105
  336. package/src/internal/utils.ts +0 -8
  337. package/src/lib/.keep +0 -4
  338. package/src/resource.ts +0 -2
  339. package/src/resources/index.ts +0 -3
  340. package/src/resources/top-level.ts +0 -551
  341. package/src/resources.ts +0 -1
  342. package/src/tsconfig.json +0 -11
  343. package/src/uploads.ts +0 -2
  344. package/src/version.ts +0 -1
  345. package/uploads.d.mts +0 -2
  346. package/uploads.d.mts.map +0 -1
  347. package/uploads.d.ts +0 -2
  348. package/uploads.d.ts.map +0 -1
  349. package/uploads.js +0 -6
  350. package/uploads.js.map +0 -1
  351. package/uploads.mjs +0 -2
  352. package/uploads.mjs.map +0 -1
  353. package/version.d.mts +0 -2
  354. package/version.d.mts.map +0 -1
  355. package/version.d.ts +0 -2
  356. package/version.d.ts.map +0 -1
  357. package/version.js +0 -5
  358. package/version.js.map +0 -1
  359. package/version.mjs +0 -2
  360. package/version.mjs.map +0 -1
@@ -0,0 +1,24 @@
1
+ import { HttpClientError, HttpClientRequest, HttpClientResponse } from '@effect/platform'
2
+ import { Effect, Schema } from 'effect'
3
+
4
+ export function unexpectedStatus(
5
+ request: HttpClientRequest.HttpClientRequest,
6
+ response: HttpClientResponse.HttpClientResponse,
7
+ ) {
8
+ return Effect.flatMap(
9
+ Effect.orElseSucceed(response.text, () => 'Unexpected status code'),
10
+ (description) =>
11
+ Effect.fail(
12
+ new HttpClientError.ResponseError({
13
+ request,
14
+ response,
15
+ reason: 'StatusCode',
16
+ description,
17
+ }),
18
+ ),
19
+ )
20
+ }
21
+
22
+ export function decodeError<A, I, R>(response: HttpClientResponse.HttpClientResponse, schema: Schema.Schema<A, I, R>) {
23
+ return Effect.flatMap(HttpClientResponse.schemaBodyJson(schema)(response), Effect.fail)
24
+ }
@@ -0,0 +1,246 @@
1
+ import { HttpClientError } from '@effect/platform'
2
+ import { Cause, Effect, HashSet, Layer, Match, Option, ParseResult } from 'effect'
3
+ import {
4
+ ExpandApiError,
5
+ ExpandClientError,
6
+ ExpandConnectionError,
7
+ type ExpandError,
8
+ ExpandSdkError,
9
+ ExpandTimeoutError,
10
+ } from './Error.js'
11
+ import * as Generated from './Generated.js'
12
+ import {
13
+ type BatchedParams,
14
+ type BatchedResponse,
15
+ ExpandService,
16
+ type ExpandServiceOptions,
17
+ type FetchJsonParams,
18
+ type FetchJsonResponse,
19
+ type FetchParams,
20
+ type FetchResponse,
21
+ type FetchSearchParams,
22
+ type FetchSearchResponse,
23
+ type GetBatchedParams,
24
+ type GetBatchedResponse,
25
+ type RequestOptions,
26
+ } from './Service.js'
27
+
28
+ const RETRYABLE_STATUS_CODES = HashSet.make(408, 409, 429, 500, 502, 503, 504)
29
+
30
+ interface TaggedApiError {
31
+ readonly _tag: string
32
+ }
33
+
34
+ function hasApiErrorTag(error: unknown, tag: string): error is TaggedApiError {
35
+ return typeof error === 'object' && error !== null && '_tag' in error && error._tag === tag
36
+ }
37
+
38
+ function apiError(status: number, error: unknown): ExpandApiError {
39
+ const message =
40
+ typeof error === 'object' && error !== null && '_tag' in error && typeof error._tag === 'string'
41
+ ? error._tag
42
+ : `HTTP ${status}`
43
+ return new ExpandApiError({ message, status, body: error, cause: error })
44
+ }
45
+
46
+ /**
47
+ * Lift a raw failure (HTTP error, parse error, codegen-typed error class, or unrelated throwable)
48
+ * into the typed `ExpandError` union surfaced by the SDK. Used by `ExpandService` to construct
49
+ * its public error channel.
50
+ */
51
+ export function toExpandError(error: unknown, timeoutMs: number): ExpandError {
52
+ return Match.value(error).pipe(
53
+ Match.when(
54
+ (error: unknown) => error instanceof Cause.TimeoutException,
55
+ (error) => new ExpandTimeoutError({ message: `Request timed out after ${timeoutMs}ms`, timeoutMs, cause: error }),
56
+ ),
57
+ Match.when(
58
+ (error: unknown) => error instanceof HttpClientError.RequestError,
59
+ (error) => new ExpandConnectionError({ message: error.message, cause: error }),
60
+ ),
61
+ Match.when(
62
+ (error: unknown) => error instanceof HttpClientError.ResponseError,
63
+ (error) =>
64
+ new ExpandApiError({
65
+ message: error.message,
66
+ status: error.response.status,
67
+ body: error.description,
68
+ cause: error,
69
+ }),
70
+ ),
71
+ Match.when(
72
+ (error: unknown) => error instanceof Generated.AuthFailed,
73
+ (error) => new ExpandApiError({ message: 'AuthFailed', status: 401, body: error, cause: error }),
74
+ ),
75
+ Match.when(
76
+ (error: unknown) => hasApiErrorTag(error, 'AuthFailed'),
77
+ (error) => apiError(401, error),
78
+ ),
79
+ Match.when(
80
+ (error: unknown) => hasApiErrorTag(error, 'AccessBlocked'),
81
+ (error) => apiError(403, error),
82
+ ),
83
+ Match.when(
84
+ (error: unknown) => error instanceof Generated.PayloadTooLarge,
85
+ (error) => new ExpandApiError({ message: 'PayloadTooLarge', status: 413, body: error, cause: error }),
86
+ ),
87
+ Match.when(
88
+ (error: unknown) => hasApiErrorTag(error, 'PayloadTooLarge'),
89
+ (error) => apiError(413, error),
90
+ ),
91
+ Match.when(
92
+ (error: unknown) => error instanceof Generated.TooManyRequests,
93
+ (error) => new ExpandApiError({ message: 'TooManyRequests', status: 429, body: error, cause: error }),
94
+ ),
95
+ Match.when(
96
+ (error: unknown) => hasApiErrorTag(error, 'TooManyRequests'),
97
+ (error) => apiError(429, error),
98
+ ),
99
+ Match.when(
100
+ (error: unknown) => error instanceof Generated.InternalError,
101
+ (error) => new ExpandApiError({ message: 'InternalError', status: 500, body: error, cause: error }),
102
+ ),
103
+ Match.when(
104
+ (error: unknown) => hasApiErrorTag(error, 'InternalError'),
105
+ (error) => apiError(500, error),
106
+ ),
107
+ Match.when(
108
+ (error: unknown) => error instanceof Generated.ServiceUnavailable,
109
+ (error) => new ExpandApiError({ message: 'ServiceUnavailable', status: 503, body: error, cause: error }),
110
+ ),
111
+ Match.when(
112
+ (error: unknown) => hasApiErrorTag(error, 'ServiceUnavailable'),
113
+ (error) => apiError(503, error),
114
+ ),
115
+ Match.when(
116
+ (error: unknown) => error instanceof Generated.HttpApiDecodeError,
117
+ (error) => new ExpandApiError({ message: 'HttpApiDecodeError', status: 400, body: error, cause: error }),
118
+ ),
119
+ Match.when(
120
+ (error: unknown) => hasApiErrorTag(error, 'HttpApiDecodeError') || hasApiErrorTag(error, 'BadRequest'),
121
+ (error) => apiError(400, error),
122
+ ),
123
+ Match.when(
124
+ (error: unknown) => hasApiErrorTag(error, 'FetchSnapshotSearchNotFound'),
125
+ (error) => apiError(404, error),
126
+ ),
127
+ // A response we couldn't decode (e.g. a 5xx whose body is empty or doesn't match the declared
128
+ // error schema) arrives as a bare ParseError with no status. Surface a clear SDK error instead
129
+ // of dumping the raw schema-mismatch tree as the message.
130
+ Match.when(
131
+ (error: unknown) => ParseResult.isParseError(error),
132
+ (error) => new ExpandSdkError({ message: 'Failed to decode the API response', cause: error }),
133
+ ),
134
+ Match.orElse(
135
+ (error) => new ExpandSdkError({ message: error instanceof Error ? error.message : String(error), cause: error }),
136
+ ),
137
+ )
138
+ }
139
+
140
+ /**
141
+ * Decide whether a failure should trigger a retry. Timeouts and connection errors are always
142
+ * retryable; API errors are retryable only for the standard transient status codes (408/409/429/5xx).
143
+ */
144
+ export function isRetryable(error: unknown, timeoutMs: number): boolean {
145
+ // An undecodable response (a transient 5xx with an empty/garbled body, a proxy error page, etc.)
146
+ // surfaces as a bare ParseError with no HTTP status, so the status-based classification below can't
147
+ // see the 5xx and the request would fail un-retried. Treat decode failures as retryable — the
148
+ // operations that retry (fetch/getBatched) are idempotent and safe to repeat.
149
+ if (ParseResult.isParseError(error)) {
150
+ return true
151
+ }
152
+ const expandError = toExpandError(error, timeoutMs)
153
+ return Match.value(expandError).pipe(
154
+ Match.when(
155
+ (error: unknown) => error instanceof ExpandTimeoutError,
156
+ () => true,
157
+ ),
158
+ Match.when(
159
+ (error: unknown) => error instanceof ExpandConnectionError,
160
+ () => true,
161
+ ),
162
+ Match.when(
163
+ (error: unknown) => error instanceof ExpandApiError,
164
+ (error) => HashSet.has(RETRYABLE_STATUS_CODES, error.status),
165
+ ),
166
+ Match.orElse(() => false),
167
+ )
168
+ }
169
+
170
+ /**
171
+ * Effect-side bridge between {@link ExpandService} and the Promise-based {@link ExpandClient}.
172
+ *
173
+ * Exposes the same fetch/batched/getBatched methods as `ExpandService` but with the typed `ExpandError`
174
+ * channel mapped to the `ExpandClientError` hierarchy that async/await consumers expect. Not exported
175
+ * from the package — Effect consumers depend on `ExpandService` directly and receive the typed
176
+ * `ExpandError` unions as-is.
177
+ */
178
+ export class InternalClient extends Effect.Service<InternalClient>()('@expandai/sdk/InternalClient', {
179
+ effect: Effect.gen(function* () {
180
+ const service = yield* ExpandService
181
+
182
+ const fetch = (
183
+ params: FetchParams,
184
+ options: RequestOptions = {},
185
+ ): Effect.Effect<FetchResponse, ExpandClientError> =>
186
+ service.fetch(params, options).pipe(Effect.mapError((error) => error.toPublicError()))
187
+
188
+ const fetchJson = (
189
+ params: FetchJsonParams,
190
+ options: RequestOptions = {},
191
+ ): Effect.Effect<FetchJsonResponse, ExpandClientError> =>
192
+ service.fetchJson(params, options).pipe(Effect.mapError((error) => error.toPublicError()))
193
+
194
+ const fetchSearch = (
195
+ params: FetchSearchParams,
196
+ options: RequestOptions = {},
197
+ ): Effect.Effect<FetchSearchResponse, ExpandClientError> =>
198
+ service.fetchSearch(params, options).pipe(Effect.mapError((error) => error.toPublicError()))
199
+
200
+ const batched = (
201
+ params: BatchedParams,
202
+ options: RequestOptions = {},
203
+ ): Effect.Effect<BatchedResponse, ExpandClientError> =>
204
+ service.batched(params, options).pipe(Effect.mapError((error) => error.toPublicError()))
205
+
206
+ const getBatched = (
207
+ id: string,
208
+ options: GetBatchedParams & RequestOptions = {},
209
+ ): Effect.Effect<GetBatchedResponse, ExpandClientError> =>
210
+ service.getBatched(id, options).pipe(Effect.mapError((error) => error.toPublicError()))
211
+
212
+ return { fetch, fetchJson, fetchSearch, batched, getBatched } as const
213
+ }),
214
+ }) {
215
+ /**
216
+ * Build a Layer providing `InternalClient` (and its `ExpandService` dependency) from the given
217
+ * options. The layer can fail at acquisition with `ExpandSdkError` (propagated from
218
+ * `ExpandService.layer`'s validation); callers running this for a Promise wrapper should pipe
219
+ * through `translateCause`, which converts via `toPublicError` to the public `ExpandClientError`.
220
+ */
221
+ static layer(options: ExpandServiceOptions = {}): Layer.Layer<InternalClient, ExpandSdkError> {
222
+ return this.Default.pipe(Layer.provide(ExpandService.layer(options)))
223
+ }
224
+
225
+ /**
226
+ * Flatten an Effect failure cause into the value to throw from a Promise wrapper. Typed errors
227
+ * (`ExpandClientError`, `ExpandSdkError`) pass through `toPublicError` if available; non-failure
228
+ * causes (defects, interruption) get wrapped in a generic `ExpandClientError`.
229
+ */
230
+ static translateCause(cause: Cause.Cause<unknown>): unknown {
231
+ const failure = Cause.failureOption(cause).pipe(Option.orElse(() => Cause.dieOption(cause)))
232
+ return Option.match(failure, {
233
+ onSome: (error) => (InternalClient.hasPublicErrorTranslator(error) ? error.toPublicError() : error),
234
+ onNone: () => new ExpandClientError(Cause.isInterrupted(cause) ? 'Request was interrupted' : Cause.pretty(cause)),
235
+ })
236
+ }
237
+
238
+ private static hasPublicErrorTranslator(error: unknown): error is { toPublicError: () => ExpandClientError } {
239
+ return (
240
+ typeof error === 'object' &&
241
+ error !== null &&
242
+ 'toPublicError' in error &&
243
+ typeof error.toPublicError === 'function'
244
+ )
245
+ }
246
+ }
@@ -0,0 +1,76 @@
1
+ // Public playground (expand.land) URL builders for citing fetch snapshots.
2
+ //
3
+ // Canonical public snapshot URLs (all public, no auth, no TTL):
4
+ //
5
+ // /s/<snapshotId> — whole snapshot
6
+ // /s/<snapshotId>/playground#focus=<id> — highlight a markdown/appendix block by node id
7
+ // /s/<snapshotId>?id=<evidenceId> — open extracted State JSON evidence
8
+ //
9
+ // A citation maps a search snippet (`source` + `location`) to the view that audits it.
10
+
11
+ import { Match } from 'effect'
12
+
13
+ export const DEFAULT_PLAYGROUND_HOST = 'https://expand.land'
14
+
15
+ export type CitationSource = 'markdown' | 'appendix' | 'statejson'
16
+
17
+ /** Snippet location subset needed to build a deep link. Tolerates `null` and `undefined`. */
18
+ export interface CitationLocation {
19
+ readonly nodeIds?: ReadonlyArray<number> | null
20
+ readonly stateJsonSourceId?: number | null
21
+ }
22
+
23
+ function normalizeHost(host: string): string {
24
+ return host.replace(/\/+$/, '')
25
+ }
26
+
27
+ /** Whole-snapshot URL: `${host}/s/${snapshotId}`. */
28
+ export function playgroundBase(snapshotId: string, host: string = DEFAULT_PLAYGROUND_HOST): string {
29
+ return `${normalizeHost(host)}/s/${encodeURIComponent(snapshotId)}`
30
+ }
31
+
32
+ /** Origin of a server-provided `meta.playground` URL, for reuse as the host (staging-safe). */
33
+ export function playgroundOrigin(metaPlayground: string): string {
34
+ return new URL(metaPlayground).origin
35
+ }
36
+
37
+ /**
38
+ * Host to build citation links against: the origin of a server-provided `meta.playground`
39
+ * (authoritative, staging-safe) when present and parseable, else the caller's fallback.
40
+ */
41
+ export function resolvePlaygroundHost(metaPlayground: string | null | undefined, fallback: string): string {
42
+ if (metaPlayground == null) {
43
+ return fallback
44
+ }
45
+ try {
46
+ return playgroundOrigin(metaPlayground)
47
+ } catch {
48
+ // meta.playground should always be a valid URL; guard defensively against a malformed value.
49
+ return fallback
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Deep link auditing a single snippet:
55
+ * - `statejson` with a source id → `?id=<stateJsonSourceId>` (opens the JSON evidence object).
56
+ * - `markdown`/`appendix` with a node id → `/playground#focus=<nodeIds[0]>` (highlights the block).
57
+ * - otherwise → the whole-snapshot base URL.
58
+ */
59
+ export function citationUrl(
60
+ snapshotId: string,
61
+ source: CitationSource,
62
+ location: CitationLocation | null | undefined,
63
+ host: string = DEFAULT_PLAYGROUND_HOST,
64
+ ): string {
65
+ const base = playgroundBase(snapshotId, host)
66
+ return Match.value(source).pipe(
67
+ Match.when('statejson', () => {
68
+ const sourceId = location?.stateJsonSourceId
69
+ return sourceId != null ? `${base}?id=${sourceId}` : base
70
+ }),
71
+ Match.orElse(() => {
72
+ const nodeId = location?.nodeIds?.[0]
73
+ return nodeId != null ? `${base}/playground#focus=${nodeId}` : base
74
+ }),
75
+ )
76
+ }
package/src/Service.ts ADDED
@@ -0,0 +1,264 @@
1
+ import { HttpClient, HttpClientRequest, HttpClientResponse } from '@effect/platform'
2
+ import { NodeHttpClient } from '@effect/platform-node'
3
+ import { Context, Duration, Effect, flow, Layer, Schedule, Schema } from 'effect'
4
+ import { ExpandSdkError } from './Error.js'
5
+ import {
6
+ type FetchObjectModeResultWithJson,
7
+ type FetchSnapshotSearchResultWithJson,
8
+ fetchObjectModeJson,
9
+ fetchSnapshotSearch,
10
+ } from './FetchJson.js'
11
+ import * as Generated from './Generated.js'
12
+ import { decodeError, unexpectedStatus } from './HttpClientHelpers.js'
13
+ import { isRetryable, toExpandError } from './Internal.js'
14
+
15
+ const DEFAULT_BASE_URL = 'https://api.expand.ai'
16
+ const DEFAULT_TIMEOUT_MS = 60_000
17
+ const DEFAULT_MAX_RETRIES = 2
18
+
19
+ /**
20
+ * Options accepted by `ExpandService.layer`. All fields are optional; defaults match `ExpandClient`.
21
+ */
22
+ export class ExpandServiceOptions extends Schema.Class<ExpandServiceOptions>('ExpandServiceOptions')(
23
+ {
24
+ /** API key. Falls back to the `EXPAND_API_KEY` environment variable. */
25
+ apiKey: Schema.optional(Schema.String).annotations({
26
+ description: 'API key. Falls back to the `EXPAND_API_KEY` environment variable.',
27
+ }),
28
+ /** API base URL. Defaults to `https://api.expand.ai`. */
29
+ baseUrl: Schema.optional(Schema.String).annotations({
30
+ description: 'API base URL. Defaults to `https://api.expand.ai`.',
31
+ }),
32
+ /**
33
+ * Total wall-clock budget in milliseconds for the operation, including retries and backoff.
34
+ * Each attempt gets `timeoutMs / (maxRetries + 1)`. Defaults to 60_000.
35
+ */
36
+ timeoutMs: Schema.optional(Schema.Number).annotations({
37
+ description:
38
+ 'Total wall-clock budget in milliseconds for the operation, including retries and backoff. ' +
39
+ 'Each attempt gets `timeoutMs / (maxRetries + 1)`. Defaults to 60_000.',
40
+ }),
41
+ /**
42
+ * Number of retry attempts for retryable failures (timeouts, connection errors, 408/409/429/5xx).
43
+ * Defaults to 2. Note: `batched()` defaults to 0 regardless of this setting; pass `{ maxRetries: N }`
44
+ * per-call to opt in.
45
+ */
46
+ maxRetries: Schema.optional(Schema.Number).annotations({
47
+ description:
48
+ 'Number of retry attempts for retryable failures (timeouts, connection errors, 408/409/429/5xx). ' +
49
+ 'Defaults to 2. Note: `batched()` defaults to 0 regardless of this setting; pass `{ maxRetries: N }` per-call to opt in.',
50
+ }),
51
+ },
52
+ { description: 'Options for constructing an `ExpandService` layer or `ExpandClient` instance.' },
53
+ ) {}
54
+
55
+ /**
56
+ * Per-request overrides accepted by `ExpandService.fetch`/`batched`/`getBatched` (and, transitively,
57
+ * by `ExpandClient`'s methods).
58
+ */
59
+ export class RequestOptions extends Schema.Class<RequestOptions>('RequestOptions')(
60
+ {
61
+ /** Override the configured `timeoutMs` for this request. Total wall-clock budget across all attempts. */
62
+ timeoutMs: Schema.optional(Schema.Number).annotations({
63
+ description: 'Override the configured `timeoutMs` for this request. Total wall-clock budget across all attempts.',
64
+ }),
65
+ /** Override the configured `maxRetries` for this request. */
66
+ maxRetries: Schema.optional(Schema.Number).annotations({
67
+ description: 'Override the configured `maxRetries` for this request.',
68
+ }),
69
+ },
70
+ { description: 'Per-request overrides for an `ExpandService` operation.' },
71
+ ) {}
72
+
73
+ export type FetchParams = typeof Generated.FetchFetchRequest.Encoded
74
+ export type FetchResponse = string
75
+ export type FetchRequestOptions = RequestOptions & typeof Generated.FetchFetchParams.Encoded
76
+ export type FetchJsonParams = typeof Generated.FetchFetchJsonRequest.Encoded
77
+ // `*WithJson` rather than the generated result: the codegen drops the statejson snippet `json`, so
78
+ // the service decodes the body with the recovering schemas (see `FetchJson.ts`).
79
+ export type FetchJsonResponse = FetchObjectModeResultWithJson
80
+ export type FetchJsonRequestOptions = RequestOptions & typeof Generated.FetchFetchJsonParams.Encoded
81
+ export type FetchSearchParams = typeof Generated.FetchFetchSearchRequest.Encoded
82
+ export type FetchSearchResponse = FetchSnapshotSearchResultWithJson
83
+ export type BatchedParams = typeof Generated.FetchBatchedRequest.Encoded
84
+ export type BatchedResponse = typeof Generated.BatchedRun.Type
85
+ export type GetBatchedParams = typeof Generated.FetchGetBatchedParams.Encoded
86
+ export type GetBatchedResponse = typeof Generated.BatchedStatus.Type
87
+
88
+ class ServiceConfig extends Schema.Class<ServiceConfig>('ExpandServiceConfig')({
89
+ apiKey: Schema.NonEmptyString,
90
+ baseUrl: Schema.NonEmptyString,
91
+ timeoutMs: Schema.Number,
92
+ maxRetries: Schema.Number,
93
+ }) {}
94
+
95
+ class ServiceConfigTag extends Context.Tag('@expandai/sdk/ExpandServiceConfig')<
96
+ ServiceConfigTag,
97
+ typeof ServiceConfig.Type
98
+ >() {}
99
+
100
+ /**
101
+ * Validate user-supplied options into a fully-defaulted `ServiceConfig`. Reads
102
+ * `EXPAND_API_KEY` from `process.env` when `options.apiKey` is missing. Used by
103
+ * `ExpandService.layer` (Effect-typed Layer error channel) and by `ExpandClient`
104
+ * (eagerly via `Effect.runSync` to preserve sync-throw constructor semantics).
105
+ */
106
+ export const buildServiceConfig = Effect.fn('buildServiceConfig')(function* (options: ExpandServiceOptions) {
107
+ const apiKey = options.apiKey ?? process.env.EXPAND_API_KEY
108
+ if (!apiKey) {
109
+ return yield* new ExpandSdkError({ message: 'Missing Expand API key. Pass apiKey or set EXPAND_API_KEY.' })
110
+ }
111
+ return yield* Schema.decode(ServiceConfig)({
112
+ apiKey,
113
+ baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
114
+ timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
115
+ maxRetries: options.maxRetries ?? DEFAULT_MAX_RETRIES,
116
+ }).pipe(Effect.mapError((error) => new ExpandSdkError({ message: 'Invalid Expand client options', cause: error })))
117
+ })
118
+
119
+ /**
120
+ * Effect-native client for the Expand API. Mirrors the {@link ExpandClient} Promise interface —
121
+ * methods accept the same `RequestOptions` per-call overrides and return Effects with the typed
122
+ * `ExpandError` channel (`ExpandApiError | ExpandConnectionError | ExpandTimeoutError | ExpandSdkError`).
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * const program = Effect.gen(function* () {
127
+ * const expand = yield* ExpandService
128
+ * return yield* expand.fetch({ url: 'https://example.com' })
129
+ * }).pipe(Effect.provide(ExpandService.layer({ apiKey: 'sk_...' })))
130
+ * ```
131
+ */
132
+ export class ExpandService extends Effect.Service<ExpandService>()('@expandai/sdk/ExpandService', {
133
+ dependencies: [NodeHttpClient.layer],
134
+ effect: Effect.gen(function* () {
135
+ const config = yield* ServiceConfigTag
136
+ const httpClient = yield* HttpClient.HttpClient
137
+ const authedClient = httpClient.pipe(
138
+ HttpClient.mapRequest(
139
+ flow(
140
+ HttpClientRequest.prependUrl(config.baseUrl),
141
+ HttpClientRequest.setHeader('x-expand-api-key', config.apiKey),
142
+ ),
143
+ ),
144
+ )
145
+ const generated = Generated.make(authedClient)
146
+ const fetchMarkdown = (params: FetchParams, queryParams: typeof Generated.FetchFetchParams.Encoded = {}) =>
147
+ HttpClientRequest.make('POST')('/v1/fetch').pipe(
148
+ // Coalesce null -> undefined: the generated `include` schema is nullable, but `setUrlParams`
149
+ // throws on a null value. `undefined` is correctly dropped (no query param emitted).
150
+ HttpClientRequest.setUrlParams({ include: queryParams.include ?? undefined }),
151
+ (req) => Effect.orDie(HttpClientRequest.bodyJson(req, params)),
152
+ Effect.flatMap((request) =>
153
+ Effect.flatMap(
154
+ authedClient.execute(request),
155
+ HttpClientResponse.matchStatus({
156
+ '200': (response) => response.text,
157
+ '400': (response) => decodeError(response, Generated.FetchFetch400),
158
+ '401': (response) => decodeError(response, Generated.AuthFailed),
159
+ '403': (response) => decodeError(response, Generated.FetchFetch403),
160
+ '413': (response) => decodeError(response, Generated.PayloadTooLarge),
161
+ '429': (response) => decodeError(response, Generated.TooManyRequests),
162
+ '500': (response) => decodeError(response, Generated.InternalError),
163
+ '503': (response) => decodeError(response, Generated.ServiceUnavailable),
164
+ orElse: (response) => unexpectedStatus(request, response),
165
+ }),
166
+ ),
167
+ ),
168
+ )
169
+
170
+ // Generic over the operation's success/error/requirement channels so callers (fetch/batched/getBatched)
171
+ // retain their full Effect typing through the wrapper.
172
+ const withRetries = Effect.fn('ExpandService.withRetries')(function* <A, E, R>(
173
+ operation: Effect.Effect<A, E, R>,
174
+ requestOptions: RequestOptions = {},
175
+ ) {
176
+ const totalTimeoutMs = requestOptions.timeoutMs ?? config.timeoutMs
177
+ const maxRetries = requestOptions.maxRetries ?? config.maxRetries
178
+ // `timeoutMs` is the wall-clock budget for the whole operation. Split it across attempts so the
179
+ // sum of per-attempt budgets equals `timeoutMs`; the outer Effect.timeout enforces the hard cap
180
+ // including retry backoff. Pipe ordering matters: per-attempt timeout must wrap the operation
181
+ // (so retry can catch its TimeoutException), and total timeout must wrap retry (so it caps
182
+ // backoff between attempts). Floor with a 1ms minimum so degenerate inputs don't produce a
183
+ // zero-millisecond budget that fires before any work happens.
184
+ const perAttemptTimeoutMs = Math.max(1, Math.floor(totalTimeoutMs / (maxRetries + 1)))
185
+ const retrySchedule = Schedule.exponential(Duration.millis(250)).pipe(
186
+ Schedule.jittered,
187
+ Schedule.compose(Schedule.recurs(maxRetries)),
188
+ Schedule.whileInput((error: unknown) => isRetryable(error, totalTimeoutMs)),
189
+ )
190
+ return yield* operation.pipe(
191
+ Effect.timeout(Duration.millis(perAttemptTimeoutMs)),
192
+ Effect.retry(retrySchedule),
193
+ Effect.timeout(Duration.millis(totalTimeoutMs)),
194
+ Effect.mapError((error) => toExpandError(error, totalTimeoutMs)),
195
+ )
196
+ })
197
+
198
+ const fetch = Effect.fn('ExpandService.fetch')(function* (
199
+ params: FetchParams,
200
+ requestOptions: FetchRequestOptions = {},
201
+ ) {
202
+ const { include, ...retryOptions } = requestOptions
203
+ return yield* withRetries(fetchMarkdown(params, { include }), retryOptions)
204
+ })
205
+
206
+ const fetchJson = Effect.fn('ExpandService.fetchJson')(function* (
207
+ params: FetchJsonParams,
208
+ requestOptions: FetchJsonRequestOptions = {},
209
+ ) {
210
+ const { include, ...retryOptions } = requestOptions
211
+ // `fetchObjectModeJson` mirrors the generated call but preserves the statejson snippet `json`.
212
+ // Coalesce null -> undefined before `setUrlParams`, which throws on null.
213
+ return yield* withRetries(
214
+ fetchObjectModeJson(authedClient, { params: { include: include ?? undefined }, payload: params }),
215
+ retryOptions,
216
+ )
217
+ })
218
+
219
+ const fetchSearch = Effect.fn('ExpandService.fetchSearch')(function* (
220
+ params: FetchSearchParams,
221
+ requestOptions: RequestOptions = {},
222
+ ) {
223
+ // `fetchSnapshotSearch` mirrors the generated call but preserves the statejson snippet `json`.
224
+ return yield* withRetries(fetchSnapshotSearch(authedClient, params), requestOptions)
225
+ })
226
+
227
+ const batched = Effect.fn('ExpandService.batched')(function* (
228
+ params: BatchedParams,
229
+ requestOptions: RequestOptions = {},
230
+ ) {
231
+ // Batched POST kicks off server-side work and the API has no idempotency-key support; a retry on
232
+ // a request that succeeded server-side but failed client-side (timeout, dropped connection)
233
+ // would create a duplicate batched run. Default to no retries; callers can opt in explicitly.
234
+ // Destructure-with-default also handles `{ maxRetries: undefined }` correctly — falls back to 0
235
+ // rather than the service-level default.
236
+ const { maxRetries = 0, ...rest } = requestOptions
237
+ return yield* withRetries(generated.fetchBatched(params), { maxRetries, ...rest })
238
+ })
239
+
240
+ const getBatched = Effect.fn('ExpandService.getBatched')(function* (
241
+ id: string,
242
+ options: GetBatchedParams & RequestOptions = {},
243
+ ) {
244
+ // Pull RequestOptions out, pass everything else through as query params. Drift-resilient: any
245
+ // new GetBatchedParams field added by codegen flows through `params` automatically.
246
+ const { timeoutMs, maxRetries, ...params } = options
247
+ return yield* withRetries(generated.fetchGetBatched(id, params), { timeoutMs, maxRetries })
248
+ })
249
+
250
+ return { fetch, fetchJson, fetchSearch, batched, getBatched } as const
251
+ }),
252
+ }) {
253
+ /**
254
+ * Build a Layer providing `ExpandService` with the given options. Validation (missing apiKey,
255
+ * Schema-rejected config) surfaces via the Layer's error channel as `ExpandSdkError`.
256
+ */
257
+ static layer(options: ExpandServiceOptions = {}) {
258
+ return Layer.unwrapEffect(
259
+ buildServiceConfig(options).pipe(
260
+ Effect.map((config) => ExpandService.Default.pipe(Layer.provide(Layer.succeed(ServiceConfigTag, config)))),
261
+ ),
262
+ )
263
+ }
264
+ }
package/src/index.ts CHANGED
@@ -1,22 +1,28 @@
1
- // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
-
3
- export { Expand as default } from './client';
4
-
5
- export { type Uploadable, toFile } from './core/uploads';
6
- export { APIPromise } from './core/api-promise';
7
- export { Expand, type ClientOptions } from './client';
1
+ export type {
2
+ BatchedParams,
3
+ BatchedResponse,
4
+ ExpandClientOptions,
5
+ FetchJsonParams,
6
+ FetchJsonRequestOptions,
7
+ FetchJsonResponse,
8
+ FetchParams,
9
+ FetchRequestOptions,
10
+ FetchResponse,
11
+ FetchSearchParams,
12
+ FetchSearchResponse,
13
+ GetBatchedParams,
14
+ GetBatchedResponse,
15
+ } from './Client.js'
16
+ export { ExpandClient } from './Client.js'
17
+ export type { ExpandError } from './Error.js'
8
18
  export {
9
- ExpandError,
10
- APIError,
11
- APIConnectionError,
12
- APIConnectionTimeoutError,
13
- APIUserAbortError,
14
- NotFoundError,
15
- ConflictError,
16
- RateLimitError,
17
- BadRequestError,
18
- AuthenticationError,
19
- InternalServerError,
20
- PermissionDeniedError,
21
- UnprocessableEntityError,
22
- } from './core/error';
19
+ ExpandApiError,
20
+ ExpandClientApiError,
21
+ ExpandClientConnectionError,
22
+ ExpandClientError,
23
+ ExpandClientTimeoutError,
24
+ ExpandConnectionError,
25
+ ExpandSdkError,
26
+ ExpandTimeoutError,
27
+ } from './Error.js'
28
+ export { ExpandService, ExpandServiceOptions, RequestOptions } from './Service.js'