@superblocksteam/sdk-api 2.0.156-next.3 → 2.0.156

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 (57) hide show
  1. package/dist/errors.d.ts +6 -6
  2. package/dist/errors.d.ts.map +1 -1
  3. package/dist/errors.js +2 -23
  4. package/dist/errors.js.map +1 -1
  5. package/dist/integrations/base/rest-api-client-base.d.ts +27 -0
  6. package/dist/integrations/base/rest-api-client-base.d.ts.map +1 -1
  7. package/dist/integrations/base/rest-api-client-base.js +46 -23
  8. package/dist/integrations/base/rest-api-client-base.js.map +1 -1
  9. package/dist/integrations/base/rest-api-integration-client.d.ts +19 -7
  10. package/dist/integrations/base/rest-api-integration-client.d.ts.map +1 -1
  11. package/dist/integrations/base/rest-api-integration-client.js +29 -2
  12. package/dist/integrations/base/rest-api-integration-client.js.map +1 -1
  13. package/dist/integrations/base/types.d.ts +43 -36
  14. package/dist/integrations/base/types.d.ts.map +1 -1
  15. package/dist/integrations/base/types.js +26 -1
  16. package/dist/integrations/base/types.js.map +1 -1
  17. package/dist/integrations/documentation-resolver.test.js +5 -11
  18. package/dist/integrations/documentation-resolver.test.js.map +1 -1
  19. package/dist/integrations/restapiintegration/client.test.d.ts +10 -0
  20. package/dist/integrations/restapiintegration/client.test.d.ts.map +1 -1
  21. package/dist/integrations/restapiintegration/client.test.js +69 -146
  22. package/dist/integrations/restapiintegration/client.test.js.map +1 -1
  23. package/dist/integrations/slack/client.test.js +1 -26
  24. package/dist/integrations/slack/client.test.js.map +1 -1
  25. package/package.json +2 -2
  26. package/src/errors.ts +5 -33
  27. package/src/integrations/anthropic/README.md +0 -7
  28. package/src/integrations/base/rest-api-client-base.ts +56 -28
  29. package/src/integrations/base/rest-api-integration-client.ts +33 -14
  30. package/src/integrations/base/types.ts +45 -41
  31. package/src/integrations/bigquery/README.md +0 -1
  32. package/src/integrations/box/README.md +0 -3
  33. package/src/integrations/cohere/README.md +0 -7
  34. package/src/integrations/documentation-resolver.test.ts +6 -13
  35. package/src/integrations/fireworks/README.md +0 -7
  36. package/src/integrations/gemini/README.md +0 -8
  37. package/src/integrations/groq/README.md +0 -7
  38. package/src/integrations/mistral/README.md +0 -7
  39. package/src/integrations/openai_v2/README.md +0 -7
  40. package/src/integrations/perplexity/README.md +0 -7
  41. package/src/integrations/restapiintegration/client.test.ts +86 -207
  42. package/src/integrations/restapiintegration/docs.manifest.json +1 -5
  43. package/src/integrations/s3/README.md +0 -1
  44. package/src/integrations/slack/client.test.ts +1 -36
  45. package/src/integrations/snowflakecortex/README.md +0 -8
  46. package/src/integrations/stabilityai/README.md +0 -7
  47. package/dist/integrations/base/decode-worker-binary-response.d.ts +0 -4
  48. package/dist/integrations/base/decode-worker-binary-response.d.ts.map +0 -1
  49. package/dist/integrations/base/decode-worker-binary-response.js +0 -49
  50. package/dist/integrations/base/decode-worker-binary-response.js.map +0 -1
  51. package/dist/integrations/base/decode-worker-binary-response.test.d.ts +0 -2
  52. package/dist/integrations/base/decode-worker-binary-response.test.d.ts.map +0 -1
  53. package/dist/integrations/base/decode-worker-binary-response.test.js +0 -81
  54. package/dist/integrations/base/decode-worker-binary-response.test.js.map +0 -1
  55. package/src/integrations/base/decode-worker-binary-response.test.ts +0 -107
  56. package/src/integrations/base/decode-worker-binary-response.ts +0 -62
  57. package/src/integrations/restapiintegration/overlays/response-types-binary.md +0 -51
@@ -277,13 +277,6 @@ All methods accept an optional `metadata` parameter as the last argument for dia
277
277
 
278
278
  ## Common Pitfalls
279
279
 
280
- ### Streaming Is Not Supported
281
-
282
- `apiRequest()` does not support streaming or Server-Sent Events. Do not set
283
- `stream: true` — streaming responses fail schema validation. Every call
284
- returns the complete response; if a UI needs real-time token streaming,
285
- handle it at the frontend layer, not through the SDK.
286
-
287
280
  ### No Specialized Methods
288
281
 
289
282
  ```typescript
@@ -257,13 +257,6 @@ All methods accept an optional `metadata` parameter as the last argument for dia
257
257
 
258
258
  ## Common Pitfalls
259
259
 
260
- ### Streaming Is Not Supported
261
-
262
- `apiRequest()` does not support streaming or Server-Sent Events. Do not set
263
- `stream: true` — streaming responses fail schema validation. Every call
264
- returns the complete response; if a UI needs real-time token streaming,
265
- handle it at the frontend layer, not through the SDK.
266
-
267
260
  ### No Specialized Methods
268
261
 
269
262
  The OpenAI client only provides `apiRequest()`. There are no other specialized methods:
@@ -189,13 +189,6 @@ All methods accept an optional `metadata` parameter as the last argument for dia
189
189
 
190
190
  ## Common Pitfalls
191
191
 
192
- ### Streaming Is Not Supported
193
-
194
- `apiRequest()` does not support streaming or Server-Sent Events. Do not set
195
- `stream: true` — streaming responses fail schema validation. Every call
196
- returns the complete response; if a UI needs real-time token streaming,
197
- handle it at the frontend layer, not through the SDK.
198
-
199
192
  ### No Specialized Methods
200
193
 
201
194
  ```typescript
@@ -1,13 +1,37 @@
1
- import { describe, expect, expectTypeOf, it, vi } from "vitest";
1
+ /**
2
+ * Tests for RestApiIntegrationPluginClientImpl (generic REST API Integration).
3
+ *
4
+ * Covers the responseType passthrough:
5
+ * - default requests keep responseType "json"; callers that pass a
6
+ * response schema still get validated results
7
+ * - the responseType option is forwarded to the orchestrator request
8
+ * - non-JSON responses (e.g. XML with responseType "text") are returned
9
+ * raw when no response schema is provided
10
+ */
11
+
12
+ import { describe, it, expect, vi } from "vitest";
2
13
  import { z } from "zod";
3
14
 
4
- import type { ActionResponseType } from "@superblocksteam/shared";
15
+ import { ActionResponseType } from "@superblocksteam/shared";
5
16
 
6
17
  import { RestApiValidationError } from "../../errors.js";
7
- import { REST_API_RESPONSE_TYPES } from "../base/types.js";
18
+ import type { RestApiResponseType } from "../base/types.js";
8
19
  import type { IntegrationConfig } from "../types.js";
9
20
  import { RestApiIntegrationPluginClientImpl } from "./client.js";
10
21
 
22
+ // ── Wire-contract assertions (verified by `pnpm typecheck`) ────────
23
+ //
24
+ // The responseType strings are sent to the orchestrator as-is; the
25
+ // accepted values are defined by ActionResponseType. This assertion
26
+ // fails compilation if the SDK union drifts outside the wire values.
27
+ //
28
+ // The SDK union is a deliberate subset of the wire values: "auto" and
29
+ // "binary" are implemented by the orchestrator but not exposed (see the
30
+ // RestApiResponseType doc for why), and "raw" is streaming-only.
31
+ const _sdkValuesAreValidWireValues: Exclude<`${ActionResponseType}`, "raw">[] =
32
+ [] as RestApiResponseType[];
33
+ void _sdkValuesAreValidWireValues;
34
+
11
35
  const TEST_CONFIG: IntegrationConfig = {
12
36
  id: "restapi-test-id",
13
37
  name: "Test REST API",
@@ -16,11 +40,6 @@ const TEST_CONFIG: IntegrationConfig = {
16
40
  };
17
41
 
18
42
  const XML_RESPONSE = `<?xml version="1.0"?><note><body>hi</body></note>`;
19
- const PDF_BYTES = [0x25, 0x50, 0x44, 0x46];
20
-
21
- function workerBufferPayload(data: unknown): unknown {
22
- return { type: "Buffer", data };
23
- }
24
43
 
25
44
  function createClient(mockResult: unknown) {
26
45
  const executeQuery = vi.fn().mockResolvedValue(mockResult);
@@ -31,14 +50,9 @@ function createClient(mockResult: unknown) {
31
50
  return { client, executeQuery };
32
51
  }
33
52
 
34
- function callApiRequest(
35
- client: RestApiIntegrationPluginClientImpl,
36
- ...args: unknown[]
37
- ): Promise<unknown> {
38
- return Reflect.apply(client.apiRequest, client, args);
39
- }
40
-
41
53
  describe("RestApiIntegrationPluginClientImpl", () => {
54
+ // ── Default JSON behavior (must not regress) ────────────────────
55
+
42
56
  describe("default JSON behavior", () => {
43
57
  it("sends responseType json when the option is omitted", async () => {
44
58
  const { client, executeQuery } = createClient({ id: "1" });
@@ -67,26 +81,19 @@ describe("RestApiIntegrationPluginClientImpl", () => {
67
81
  });
68
82
 
69
83
  it("throws RestApiValidationError when the response does not match the schema", async () => {
70
- const payload = XML_RESPONSE;
71
- const { client } = createClient(payload);
84
+ const { client } = createClient(XML_RESPONSE);
72
85
 
73
- try {
74
- await client.apiRequest(
86
+ await expect(
87
+ client.apiRequest(
75
88
  { method: "GET", path: "/users" },
76
89
  { response: z.object({ id: z.string() }) },
77
- );
78
- } catch (error) {
79
- expect(error).toBeInstanceOf(RestApiValidationError);
80
- if (!(error instanceof RestApiValidationError)) {
81
- throw error;
82
- }
83
- expect(error.details.data).toBe(payload);
84
- return;
85
- }
86
- throw new Error("Expected JSON response validation to fail");
90
+ ),
91
+ ).rejects.toThrow(RestApiValidationError);
87
92
  });
88
93
  });
89
94
 
95
+ // ── responseType passthrough ────────────────────────────────────
96
+
90
97
  describe("responseType passthrough", () => {
91
98
  it("forwards responseType text to the orchestrator request", async () => {
92
99
  const { client, executeQuery } = createClient(XML_RESPONSE);
@@ -145,6 +152,8 @@ describe("RestApiIntegrationPluginClientImpl", () => {
145
152
  });
146
153
 
147
154
  it("returns an empty string unchanged for responseType text", async () => {
155
+ // An empty text body legitimately decodes to "" — the null/undefined
156
+ // guard must not reject it.
148
157
  const { client } = createClient("");
149
158
 
150
159
  const result = await client.apiRequest({
@@ -157,6 +166,10 @@ describe("RestApiIntegrationPluginClientImpl", () => {
157
166
  });
158
167
 
159
168
  it("rejects null and undefined results for every response type", async () => {
169
+ // Neither value is a legitimate decode result for the exposed
170
+ // response types: JSON parses to a value the schema sees, and an
171
+ // empty text body decodes to "". Either means a broken execution
172
+ // contract, so both throw.
160
173
  for (const badResult of [null, undefined]) {
161
174
  const { client: textClient } = createClient(badResult);
162
175
  await expect(
@@ -167,15 +180,8 @@ describe("RestApiIntegrationPluginClientImpl", () => {
167
180
  }),
168
181
  ).rejects.toThrow(RestApiValidationError);
169
182
 
170
- const { client: binaryClient } = createClient(badResult);
171
- await expect(
172
- binaryClient.apiRequest({
173
- method: "GET",
174
- path: "/broken",
175
- responseType: "binary",
176
- }),
177
- ).rejects.toThrow(RestApiValidationError);
178
-
183
+ // JSON mode always goes through the schema overload; the bad
184
+ // result is rejected before validation runs.
179
185
  const { client: jsonClient } = createClient(badResult);
180
186
  await expect(
181
187
  jsonClient.apiRequest(
@@ -187,109 +193,14 @@ describe("RestApiIntegrationPluginClientImpl", () => {
187
193
  });
188
194
  });
189
195
 
190
- describe("responseType binary", () => {
191
- it("forwards responseType binary and returns decoded bytes", async () => {
192
- const { client, executeQuery } = createClient(
193
- workerBufferPayload(PDF_BYTES),
194
- );
195
-
196
- const result = await client.apiRequest({
197
- method: "GET",
198
- path: "/file.pdf",
199
- responseType: "binary",
200
- });
201
-
202
- expect(executeQuery).toHaveBeenCalledWith(
203
- expect.objectContaining({ responseType: "binary" }),
204
- undefined,
205
- undefined,
206
- );
207
- expect(result).toBeInstanceOf(Uint8Array);
208
- expect(result.constructor).toBe(Uint8Array);
209
- expect(Array.from(result)).toEqual(PDF_BYTES);
210
- });
211
-
212
- it("rejects malformed binary data before applying a response schema", async () => {
213
- const malformed = workerBufferPayload([256]);
214
- const { client, executeQuery } = createClient(malformed);
215
- const workerShapeSchema = z.object({
216
- type: z.literal("Buffer"),
217
- data: z.array(z.number()),
218
- });
219
-
220
- await expect(
221
- callApiRequest(
222
- client,
223
- { method: "GET", path: "/file.pdf", responseType: "binary" },
224
- { response: workerShapeSchema },
225
- ),
226
- ).rejects.toThrow(RestApiValidationError);
227
- expect(executeQuery).toHaveBeenCalled();
228
- });
229
-
230
- it("accepts response schemas that transform bytes to bytes", async () => {
231
- const { client } = createClient(workerBufferPayload(PDF_BYTES));
232
-
233
- const result = await client.apiRequest(
234
- { method: "GET", path: "/file.pdf", responseType: "binary" },
235
- {
236
- response: z
237
- .instanceof(Uint8Array)
238
- .refine((bytes) => bytes[0] === 0x25)
239
- .transform((bytes) => bytes.slice(1)),
240
- },
241
- );
242
-
243
- expect(Array.from(result)).toEqual(PDF_BYTES.slice(1));
244
- });
245
-
246
- it("throws RestApiValidationError when the schema rejects normalized bytes", async () => {
247
- const { client } = createClient(workerBufferPayload(PDF_BYTES));
248
-
249
- await expect(
250
- client.apiRequest(
251
- { method: "GET", path: "/file.pdf", responseType: "binary" },
252
- {
253
- response: z
254
- .instanceof(Uint8Array)
255
- .refine((bytes) => bytes.byteLength > 64),
256
- },
257
- ),
258
- ).rejects.toThrow(RestApiValidationError);
259
- });
260
-
261
- it("redacts binary data from response validation errors", async () => {
262
- const bytes = Array.from({ length: 4096 }, () => 0);
263
- const { client } = createClient(workerBufferPayload(bytes));
264
-
265
- try {
266
- await client.apiRequest(
267
- { method: "GET", path: "/file.pdf", responseType: "binary" },
268
- {
269
- response: z
270
- .instanceof(Uint8Array)
271
- .refine((value) => value.byteLength < 1024),
272
- },
273
- );
274
- } catch (error) {
275
- expect(error).toBeInstanceOf(RestApiValidationError);
276
- if (!(error instanceof RestApiValidationError)) {
277
- throw error;
278
- }
279
- expect(error.details.data).toEqual({
280
- dataType: "binary",
281
- redacted: true,
282
- });
283
- return;
284
- }
285
- throw new Error("Expected binary response validation to fail");
286
- });
287
- });
196
+ // ── Request-body validation via the schema-less overload ────────
288
197
 
289
198
  describe("request body validation", () => {
290
199
  it("throws RestApiValidationError for an invalid body with a body-only schema", async () => {
291
200
  const { client, executeQuery } = createClient({ ok: true });
292
201
 
202
+ // Runtime-invalid bodies reach this path via dynamic data (user
203
+ // input, parsed JSON) that the compiler cannot check.
293
204
  const dynamicBody: unknown = JSON.parse('{"amount":"not-a-number"}');
294
205
 
295
206
  await expect(
@@ -331,12 +242,23 @@ describe("RestApiIntegrationPluginClientImpl", () => {
331
242
  });
332
243
  });
333
244
 
245
+ // ── Runtime contract enforcement ─────────────────────────────────
246
+ //
247
+ // The overloads make these calls unrepresentable in TypeScript, but
248
+ // user API code executes as esbuild-bundled JS with no type
249
+ // enforcement — the same contract must hold at runtime.
250
+
334
251
  describe("runtime contract enforcement", () => {
252
+ type UncheckedApiRequest = (...args: unknown[]) => Promise<unknown>;
253
+
335
254
  it("rejects a schema-less call in default JSON mode without issuing the request", async () => {
336
255
  const { client, executeQuery } = createClient({ ok: true });
337
256
 
338
257
  await expect(
339
- callApiRequest(client, { method: "GET", path: "/users" }),
258
+ (client.apiRequest as UncheckedApiRequest)({
259
+ method: "GET",
260
+ path: "/users",
261
+ }),
340
262
  ).rejects.toThrow(RestApiValidationError);
341
263
  expect(executeQuery).not.toHaveBeenCalled();
342
264
  });
@@ -345,8 +267,7 @@ describe("RestApiIntegrationPluginClientImpl", () => {
345
267
  const { client, executeQuery } = createClient({ ok: true });
346
268
 
347
269
  await expect(
348
- callApiRequest(
349
- client,
270
+ (client.apiRequest as UncheckedApiRequest)(
350
271
  {
351
272
  method: "POST",
352
273
  path: "/orders",
@@ -359,32 +280,27 @@ describe("RestApiIntegrationPluginClientImpl", () => {
359
280
  expect(executeQuery).not.toHaveBeenCalled();
360
281
  });
361
282
 
362
- it("rejects auto, which can yield unvalidated JSON, and raw, which is streaming-only", async () => {
363
- for (const responseType of ["auto", "raw"]) {
364
- const { client, executeQuery } = createClient({ ok: true });
283
+ it("rejects an unexposed responseType value without issuing the request", async () => {
284
+ const { client, executeQuery } = createClient({ ok: true });
365
285
 
366
- await expect(
367
- callApiRequest(client, {
368
- method: "GET",
369
- path: "/report",
370
- responseType,
371
- }),
372
- ).rejects.toThrow(RestApiValidationError);
373
- expect(executeQuery).not.toHaveBeenCalled();
374
- }
286
+ await expect(
287
+ (client.apiRequest as UncheckedApiRequest)({
288
+ method: "GET",
289
+ path: "/report",
290
+ responseType: "auto",
291
+ }),
292
+ ).rejects.toThrow(RestApiValidationError);
293
+ expect(executeQuery).not.toHaveBeenCalled();
375
294
  });
376
295
  });
377
296
 
378
- describe("overload resolution", () => {
379
- it("keeps public response types within the worker contract", () => {
380
- expectTypeOf<(typeof REST_API_RESPONSE_TYPES)[number]>().toMatchTypeOf<
381
- Exclude<`${ActionResponseType}`, "raw">
382
- >();
383
- });
297
+ // ── Compile-time overload contracts (verified by `pnpm typecheck`) ──
384
298
 
299
+ describe("overload resolution", () => {
385
300
  it("keeps typed results for schema callers and unknown for schema-less calls", async () => {
386
301
  const { client } = createClient({ id: "1" });
387
302
 
303
+ // With a response schema: resolves to the typed overload.
388
304
  const typed: Promise<{ id: string }> = client.apiRequest(
389
305
  { method: "GET", path: "/users" },
390
306
  { response: z.object({ id: z.string() }) },
@@ -393,6 +309,7 @@ describe("RestApiIntegrationPluginClientImpl", () => {
393
309
 
394
310
  const { client: rawClient } = createClient(XML_RESPONSE);
395
311
 
312
+ // Without a schema: resolves to the raw overload returning unknown.
396
313
  const raw: Promise<unknown> = rawClient.apiRequest({
397
314
  method: "GET",
398
315
  path: "/report.xml",
@@ -408,58 +325,20 @@ describe("RestApiIntegrationPluginClientImpl", () => {
408
325
  });
409
326
  await wrong;
410
327
 
411
- // @ts-expect-error unvalidated JSON is unrepresentable; schema-less calls must opt into a non-JSON responseType
328
+ // The remaining cases are rejected twice over: at compile time by
329
+ // the overloads (@ts-expect-error) and at runtime by the contract
330
+ // guards, since bundled user code carries no types.
331
+
332
+ // @ts-expect-error unvalidated JSON is unrepresentable — schema-less
333
+ // calls must opt into a non-JSON responseType
412
334
  const unvalidatedJson = rawClient.apiRequest({
413
335
  method: "GET",
414
336
  path: "/users",
415
337
  });
416
338
  await expect(unvalidatedJson).rejects.toThrow(RestApiValidationError);
417
- });
418
-
419
- it("types schema-less binary responses as Uint8Array", async () => {
420
- const { client: binaryClient } = createClient(
421
- workerBufferPayload(PDF_BYTES),
422
- );
423
-
424
- const binary: Promise<Uint8Array> = binaryClient.apiRequest({
425
- method: "GET",
426
- path: "/file.pdf",
427
- responseType: "binary",
428
- });
429
- expectTypeOf(binary).toEqualTypeOf<Promise<Uint8Array>>();
430
- expect(Array.from(await binary)).toEqual(PDF_BYTES);
431
-
432
- // @ts-expect-error schema-less binary apiRequest returns Uint8Array
433
- const wrongBinary: Promise<string> = binaryClient.apiRequest({
434
- method: "GET",
435
- path: "/file.pdf",
436
- responseType: "binary",
437
- });
438
- await wrongBinary;
439
- });
440
-
441
- it("rejects binary response schemas that transform bytes to another type", () => {
442
- const { client: binaryClient } = createClient(
443
- workerBufferPayload(PDF_BYTES),
444
- );
445
339
 
446
- // @ts-expect-error binary response schemas must output Uint8Array
447
- binaryClient.apiRequest(
448
- {
449
- method: "GET",
450
- path: "/file.pdf",
451
- responseType: "binary",
452
- },
453
- {
454
- response: z
455
- .instanceof(Uint8Array)
456
- .transform((bytes) => bytes.byteLength),
457
- },
458
- );
459
- });
460
-
461
- it("rejects response types outside the public SDK contract", async () => {
462
- const { client: rawClient } = createClient(XML_RESPONSE);
340
+ // "auto" and "binary" are valid wire values but deliberately not
341
+ // exposed in the SDK union (see RestApiResponseType).
463
342
  const autoCall = rawClient.apiRequest({
464
343
  method: "GET",
465
344
  path: "/report.xml",
@@ -468,13 +347,13 @@ describe("RestApiIntegrationPluginClientImpl", () => {
468
347
  });
469
348
  await expect(autoCall).rejects.toThrow(RestApiValidationError);
470
349
 
471
- const rawCall = rawClient.apiRequest({
350
+ const binaryCall = rawClient.apiRequest({
472
351
  method: "GET",
473
352
  path: "/report.xml",
474
- // @ts-expect-error "raw" is not an exposed responseType
475
- responseType: "raw",
353
+ // @ts-expect-error "binary" is not an exposed responseType
354
+ responseType: "binary",
476
355
  });
477
- await expect(rawCall).rejects.toThrow(RestApiValidationError);
356
+ await expect(binaryCall).rejects.toThrow(RestApiValidationError);
478
357
  });
479
358
  });
480
359
  });
@@ -4,11 +4,7 @@
4
4
  "overlays": [
5
5
  {
6
6
  "file": "overlays/response-types.md",
7
- "sdkVersionRange": ">=0.0.3 <0.0.4"
8
- },
9
- {
10
- "file": "overlays/response-types-binary.md",
11
- "sdkVersionRange": ">=0.0.4"
7
+ "sdkVersionRange": ">=0.0.3"
12
8
  },
13
9
  {
14
10
  "file": "overlays/response-types-unsupported.md",
@@ -25,7 +25,6 @@ import { api, z, s3 } from "@superblocksteam/sdk-api";
25
25
  const PROD_S3 = "a1b2c3d4-5678-90ab-cdef-s300000001";
26
26
 
27
27
  export default api({
28
- name: "ListBucketObjects",
29
28
  integrations: {
30
29
  storage: s3(PROD_S3),
31
30
  },
@@ -12,7 +12,6 @@ import { describe, it, expect, vi } from "vitest";
12
12
  import { z } from "zod";
13
13
 
14
14
  import { RestApiValidationError } from "../../errors.js";
15
- import { REDACTED_BINARY_RESPONSE_DATA } from "../base/decode-worker-binary-response.js";
16
15
  import type { IntegrationConfig } from "../types.js";
17
16
  import { SlackClientImpl } from "./client.js";
18
17
  import type { SlackErrorResponse } from "./types.js";
@@ -509,41 +508,7 @@ describe("SlackClientImpl", () => {
509
508
  });
510
509
  });
511
510
 
512
- describe("responseType binary", () => {
513
- const pdfBytes = [0x25, 0x50, 0x44, 0x46];
514
- const workerPayload = { type: "Buffer", data: pdfBytes };
515
-
516
- it("decodes worker Buffer JSON and redacts it from validation errors", async () => {
517
- const { client, executeQuery } = createClient(workerPayload);
518
-
519
- try {
520
- await client.apiRequest(
521
- {
522
- method: "GET",
523
- path: "/files.download",
524
- responseType: "binary",
525
- },
526
- { response: ChannelsSchema },
527
- );
528
- } catch (error) {
529
- expect(error).toBeInstanceOf(RestApiValidationError);
530
- if (!(error instanceof RestApiValidationError)) {
531
- throw error;
532
- }
533
- expect(executeQuery).toHaveBeenCalledWith(
534
- expect.objectContaining({ responseType: "binary" }),
535
- undefined,
536
- undefined,
537
- );
538
- expect(error.details.data).toEqual(REDACTED_BINARY_RESPONSE_DATA);
539
- expect(error.details.data).not.toEqual(workerPayload);
540
- return;
541
- }
542
- throw new Error(
543
- "Expected Slack binary apiRequest to fail envelope validation",
544
- );
545
- });
546
- });
511
+ // ── Type narrowing (compile-time verification) ─────────────────
547
512
 
548
513
  describe("type narrowing", () => {
549
514
  it("narrows to error response fields when ok is false", async () => {
@@ -108,14 +108,6 @@ All methods accept an optional `metadata` parameter as the last argument for dia
108
108
 
109
109
  ## Common Pitfalls
110
110
 
111
- ### Streaming Is Not Supported
112
-
113
- `apiRequest()` does not support streaming or Server-Sent Events. Always set
114
- `stream: false` in Cortex request bodies (as the examples do) — a streaming
115
- response fails schema validation. Every call returns the complete response;
116
- if a UI needs real-time token streaming, handle it at the frontend layer,
117
- not through the SDK.
118
-
119
111
  ### No Specialized Methods
120
112
 
121
113
  The Snowflake Cortex client only provides `apiRequest()`. There are no other specialized methods:
@@ -234,13 +234,6 @@ All methods accept an optional `metadata` parameter as the last argument for dia
234
234
 
235
235
  ## Common Pitfalls
236
236
 
237
- ### Streaming Is Not Supported
238
-
239
- `apiRequest()` does not support streaming or Server-Sent Events. Do not set
240
- `stream: true` — streaming responses fail schema validation. Every call
241
- returns the complete response; if a UI needs real-time token streaming,
242
- handle it at the frontend layer, not through the SDK.
243
-
244
237
  ### No Specialized Methods
245
238
 
246
239
  ```typescript
@@ -1,4 +0,0 @@
1
- import { REDACTED_BINARY_RESPONSE_DATA } from "../../errors.js";
2
- export { REDACTED_BINARY_RESPONSE_DATA };
3
- export declare function decodeWorkerBinaryResponse(value: unknown): Uint8Array;
4
- //# sourceMappingURL=decode-worker-binary-response.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"decode-worker-binary-response.d.ts","sourceRoot":"","sources":["../../../src/integrations/base/decode-worker-binary-response.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,6BAA6B,EAE9B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,6BAA6B,EAAE,CAAC;AA0CzC,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAYrE"}
@@ -1,49 +0,0 @@
1
- import { z } from "zod";
2
- import { REDACTED_BINARY_RESPONSE_DATA, RestApiValidationError, } from "../../errors.js";
3
- export { REDACTED_BINARY_RESPONSE_DATA };
4
- const workerBinaryResponseSchema = z.union([
5
- z.instanceof(Uint8Array).transform((value) => new Uint8Array(value)),
6
- z
7
- .object({
8
- data: z.unknown(),
9
- type: z.literal("Buffer"),
10
- })
11
- .transform((value, context) => {
12
- if (!Array.isArray(value.data)) {
13
- context.addIssue({
14
- code: z.ZodIssueCode.custom,
15
- message: "data must be an array of bytes",
16
- path: ["data"],
17
- });
18
- return z.NEVER;
19
- }
20
- const bytes = new Uint8Array(value.data.length);
21
- for (let index = 0; index < value.data.length; index += 1) {
22
- const item = value.data[index];
23
- if (typeof item !== "number" ||
24
- !Number.isInteger(item) ||
25
- item < 0 ||
26
- item > 255) {
27
- context.addIssue({
28
- code: z.ZodIssueCode.custom,
29
- message: "byte must be an integer from 0 through 255",
30
- path: ["data", index],
31
- });
32
- return z.NEVER;
33
- }
34
- bytes[index] = item;
35
- }
36
- return bytes;
37
- }),
38
- ]);
39
- export function decodeWorkerBinaryResponse(value) {
40
- const result = workerBinaryResponseSchema.safeParse(value);
41
- if (!result.success) {
42
- throw new RestApiValidationError(`Binary response is malformed: ${result.error.message}`, {
43
- data: REDACTED_BINARY_RESPONSE_DATA,
44
- zodError: result.error,
45
- });
46
- }
47
- return result.data;
48
- }
49
- //# sourceMappingURL=decode-worker-binary-response.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"decode-worker-binary-response.js","sourceRoot":"","sources":["../../../src/integrations/base/decode-worker-binary-response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,6BAA6B,EAAE,CAAC;AAEzC,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC;IACzC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IACpE,CAAC;SACE,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;QACjB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;KAC1B,CAAC;SACD,SAAS,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QAC5B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,QAAQ,CAAC;gBACf,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,OAAO,EAAE,gCAAgC;gBACzC,IAAI,EAAE,CAAC,MAAM,CAAC;aACf,CAAC,CAAC;YACH,OAAO,CAAC,CAAC,KAAK,CAAC;QACjB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/B,IACE,OAAO,IAAI,KAAK,QAAQ;gBACxB,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;gBACvB,IAAI,GAAG,CAAC;gBACR,IAAI,GAAG,GAAG,EACV,CAAC;gBACD,OAAO,CAAC,QAAQ,CAAC;oBACf,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;oBAC3B,OAAO,EAAE,4CAA4C;oBACrD,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;iBACtB,CAAC,CAAC;gBACH,OAAO,CAAC,CAAC,KAAK,CAAC;YACjB,CAAC;YACD,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QACtB,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;CACL,CAAC,CAAC;AAEH,MAAM,UAAU,0BAA0B,CAAC,KAAc;IACvD,MAAM,MAAM,GAAG,0BAA0B,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC3D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,sBAAsB,CAC9B,iCAAiC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EACvD;YACE,IAAI,EAAE,6BAA6B;YACnC,QAAQ,EAAE,MAAM,CAAC,KAAK;SACvB,CACF,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=decode-worker-binary-response.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"decode-worker-binary-response.test.d.ts","sourceRoot":"","sources":["../../../src/integrations/base/decode-worker-binary-response.test.ts"],"names":[],"mappings":""}