@superblocksteam/sdk-api 0.0.12-body-types → 0.0.12

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 (83) hide show
  1. package/README.md +23 -0
  2. package/dist/errors.d.ts.map +1 -1
  3. package/dist/errors.js +1 -44
  4. package/dist/errors.js.map +1 -1
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/integrations/base/index.d.ts +1 -2
  9. package/dist/integrations/base/index.d.ts.map +1 -1
  10. package/dist/integrations/base/index.js +0 -1
  11. package/dist/integrations/base/index.js.map +1 -1
  12. package/dist/integrations/base/rest-api-client-base.d.ts.map +1 -1
  13. package/dist/integrations/base/rest-api-client-base.js +4 -18
  14. package/dist/integrations/base/rest-api-client-base.js.map +1 -1
  15. package/dist/integrations/base/types.d.ts +5 -40
  16. package/dist/integrations/base/types.d.ts.map +1 -1
  17. package/dist/integrations/base/types.js +0 -7
  18. package/dist/integrations/base/types.js.map +1 -1
  19. package/dist/integrations/documentation-resolver.test.js +1 -20
  20. package/dist/integrations/documentation-resolver.test.js.map +1 -1
  21. package/dist/integrations/dynamodb/client.d.ts +6 -2
  22. package/dist/integrations/dynamodb/client.d.ts.map +1 -1
  23. package/dist/integrations/dynamodb/client.js +83 -10
  24. package/dist/integrations/dynamodb/client.js.map +1 -1
  25. package/dist/integrations/dynamodb/client.test.d.ts +8 -0
  26. package/dist/integrations/dynamodb/client.test.d.ts.map +1 -0
  27. package/dist/integrations/dynamodb/client.test.js +198 -0
  28. package/dist/integrations/dynamodb/client.test.js.map +1 -0
  29. package/dist/integrations/dynamodb/index.d.ts +1 -1
  30. package/dist/integrations/dynamodb/index.d.ts.map +1 -1
  31. package/dist/integrations/dynamodb/index.js.map +1 -1
  32. package/dist/integrations/dynamodb/types.d.ts +27 -1
  33. package/dist/integrations/dynamodb/types.d.ts.map +1 -1
  34. package/dist/integrations/index.d.ts +1 -1
  35. package/dist/integrations/index.d.ts.map +1 -1
  36. package/dist/integrations/index.js.map +1 -1
  37. package/dist/integrations/slack/client.test.js +0 -23
  38. package/dist/integrations/slack/client.test.js.map +1 -1
  39. package/dist/runtime/context.d.ts +6 -0
  40. package/dist/runtime/context.d.ts.map +1 -1
  41. package/dist/runtime/context.js +2 -1
  42. package/dist/runtime/context.js.map +1 -1
  43. package/dist/runtime/executor.d.ts +6 -0
  44. package/dist/runtime/executor.d.ts.map +1 -1
  45. package/dist/runtime/executor.js +1 -0
  46. package/dist/runtime/executor.js.map +1 -1
  47. package/dist/types.d.ts +10 -0
  48. package/dist/types.d.ts.map +1 -1
  49. package/package.json +1 -1
  50. package/src/errors.ts +1 -52
  51. package/src/index.ts +1 -0
  52. package/src/integrations/base/index.ts +0 -7
  53. package/src/integrations/base/rest-api-client-base.ts +4 -18
  54. package/src/integrations/base/types.ts +5 -59
  55. package/src/integrations/documentation-resolver.test.ts +1 -24
  56. package/src/integrations/dynamodb/README.md +33 -12
  57. package/src/integrations/dynamodb/client.test.ts +254 -0
  58. package/src/integrations/dynamodb/client.ts +121 -16
  59. package/src/integrations/dynamodb/index.ts +5 -1
  60. package/src/integrations/dynamodb/types.ts +33 -1
  61. package/src/integrations/index.ts +1 -0
  62. package/src/integrations/restapiintegration/docs.manifest.json +0 -8
  63. package/src/integrations/slack/client.test.ts +0 -33
  64. package/src/runtime/context.ts +9 -0
  65. package/src/runtime/executor.ts +8 -0
  66. package/src/types.ts +11 -0
  67. package/dist/integrations/base/request-body.d.ts +0 -21
  68. package/dist/integrations/base/request-body.d.ts.map +0 -1
  69. package/dist/integrations/base/request-body.js +0 -322
  70. package/dist/integrations/base/request-body.js.map +0 -1
  71. package/dist/integrations/base/request-body.test.d.ts +0 -2
  72. package/dist/integrations/base/request-body.test.d.ts.map +0 -1
  73. package/dist/integrations/base/request-body.test.js +0 -324
  74. package/dist/integrations/base/request-body.test.js.map +0 -1
  75. package/dist/integrations/restapiintegration/client.body-types.test.d.ts +0 -2
  76. package/dist/integrations/restapiintegration/client.body-types.test.d.ts.map +0 -1
  77. package/dist/integrations/restapiintegration/client.body-types.test.js +0 -145
  78. package/dist/integrations/restapiintegration/client.body-types.test.js.map +0 -1
  79. package/src/integrations/base/request-body.test.ts +0 -402
  80. package/src/integrations/base/request-body.ts +0 -548
  81. package/src/integrations/restapiintegration/client.body-types.test.ts +0 -214
  82. package/src/integrations/restapiintegration/overlays/request-body-types-unsupported.md +0 -7
  83. package/src/integrations/restapiintegration/overlays/request-body-types.md +0 -106
@@ -1,214 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { z } from "zod";
3
-
4
- import { RestApiValidationError } from "../../errors.js";
5
- import type { IntegrationConfig } from "../types.js";
6
- import { RestApiIntegrationPluginClientImpl } from "./client.js";
7
-
8
- const TEST_CONFIG: IntegrationConfig = {
9
- id: "restapi-test-id",
10
- name: "Test REST API",
11
- pluginId: "restapiintegration",
12
- configuration: {},
13
- };
14
-
15
- const JsonResponseSchema = z.object({ ok: z.boolean() });
16
-
17
- function createClient() {
18
- const executeQuery = vi.fn().mockResolvedValue({ ok: true });
19
- const client = new RestApiIntegrationPluginClientImpl(
20
- TEST_CONFIG,
21
- executeQuery,
22
- );
23
- return { client, executeQuery };
24
- }
25
-
26
- function callApiRequest(
27
- client: RestApiIntegrationPluginClientImpl,
28
- ...args: unknown[]
29
- ): Promise<unknown> {
30
- return Reflect.apply(client.apiRequest, client, args);
31
- }
32
-
33
- describe("RestApiIntegrationPluginClientImpl request body types", () => {
34
- it("preserves omitted and explicit JSON body wire behavior", async () => {
35
- for (const bodyType of [undefined, "json"] as const) {
36
- const { client, executeQuery } = createClient();
37
- await client.apiRequest(
38
- { method: "POST", path: "/payments", body: { amount: 42 }, bodyType },
39
- { response: JsonResponseSchema },
40
- );
41
- expect(executeQuery).toHaveBeenCalledWith(
42
- expect.objectContaining({
43
- body: JSON.stringify({ amount: 42 }),
44
- bodyType: "jsonBody",
45
- }),
46
- undefined,
47
- undefined,
48
- );
49
- }
50
- });
51
-
52
- it("sends raw string bodies as rawBody", async () => {
53
- const { client, executeQuery } = createClient();
54
- await client.apiRequest(
55
- {
56
- method: "POST",
57
- path: "/xml",
58
- body: "<note>hello</note>",
59
- bodyType: "raw",
60
- },
61
- { response: JsonResponseSchema },
62
- );
63
- expect(executeQuery).toHaveBeenCalledWith(
64
- expect.objectContaining({
65
- body: "<note>hello</note>",
66
- bodyType: "rawBody",
67
- }),
68
- undefined,
69
- undefined,
70
- );
71
- });
72
-
73
- it("sends formUrlencoded bodies as rawBody with injected Content-Type", async () => {
74
- const { client, executeQuery } = createClient();
75
- await client.apiRequest(
76
- {
77
- method: "POST",
78
- path: "/charges",
79
- body: { amount: 2000, currency: "usd", "metadata[order_id]": "6735" },
80
- bodyType: "formUrlencoded",
81
- },
82
- { response: JsonResponseSchema },
83
- );
84
- expect(executeQuery).toHaveBeenCalledWith(
85
- expect.objectContaining({
86
- body: "amount=2000&currency=usd&metadata%5Border_id%5D=6735",
87
- bodyType: "rawBody",
88
- headers: [
89
- { key: "Content-Type", value: "application/x-www-form-urlencoded" },
90
- ],
91
- }),
92
- undefined,
93
- undefined,
94
- );
95
- });
96
-
97
- it("sends binary bodies as base64 binaryBody with default Content-Type", async () => {
98
- const bytes = Uint8Array.from([137, 80, 78, 71]);
99
- const { client, executeQuery } = createClient();
100
- await client.apiRequest(
101
- {
102
- method: "PUT",
103
- path: "/files/report.png",
104
- body: bytes,
105
- bodyType: "binary",
106
- },
107
- { response: JsonResponseSchema },
108
- );
109
- expect(executeQuery).toHaveBeenCalledWith(
110
- expect.objectContaining({
111
- body: Buffer.from(bytes).toString("base64"),
112
- bodyType: "binaryBody",
113
- headers: [{ key: "Content-Type", value: "application/octet-stream" }],
114
- }),
115
- undefined,
116
- undefined,
117
- );
118
- });
119
-
120
- it("sends text multipart file parts as formData", async () => {
121
- const { client, executeQuery } = createClient();
122
- await client.apiRequest(
123
- {
124
- method: "POST",
125
- path: "/upload",
126
- body: {
127
- note: "hello",
128
- file: { value: "contents", filename: "note.txt" },
129
- },
130
- bodyType: "multipartForm",
131
- },
132
- { response: JsonResponseSchema },
133
- );
134
- expect(executeQuery).toHaveBeenCalledWith(
135
- expect.objectContaining({
136
- bodyType: "formData",
137
- formData: [
138
- { key: "note", value: "hello" },
139
- { key: "file", value: "contents", file: { filename: "note.txt" } },
140
- ],
141
- }),
142
- undefined,
143
- undefined,
144
- );
145
- });
146
-
147
- it("sends mixed multipart file parts as formDataBase64 with no top-level body", async () => {
148
- const bytes = Uint8Array.from([137, 80, 78, 71]);
149
- const { client, executeQuery } = createClient();
150
- await client.apiRequest(
151
- {
152
- method: "POST",
153
- path: "/upload",
154
- body: { note: "mixed", image: { value: bytes, filename: "b.png" } },
155
- bodyType: "multipartForm",
156
- },
157
- { response: JsonResponseSchema },
158
- );
159
- expect(executeQuery).toHaveBeenCalledWith(
160
- expect.objectContaining({
161
- bodyType: "formDataBase64",
162
- formData: [
163
- { key: "note", value: "mixed" },
164
- {
165
- key: "image",
166
- value: Buffer.from(bytes).toString("base64"),
167
- file: { filename: "b.png" },
168
- },
169
- ],
170
- }),
171
- undefined,
172
- undefined,
173
- );
174
- expect(executeQuery.mock.calls[0][0]).not.toHaveProperty("body");
175
- });
176
-
177
- it("rejects invalid bodyType and invalid bodies before executeQuery", async () => {
178
- for (const bodyType of [
179
- "form",
180
- "jsonBody",
181
- "rawBody",
182
- "formData",
183
- "fileForm",
184
- "binaryBody",
185
- "formDataBase64",
186
- ]) {
187
- const { client, executeQuery } = createClient();
188
- await expect(
189
- callApiRequest(
190
- client,
191
- { method: "POST", path: "/bad", body: {}, bodyType },
192
- { response: JsonResponseSchema },
193
- ),
194
- ).rejects.toThrow(RestApiValidationError);
195
- expect(executeQuery).not.toHaveBeenCalled();
196
- }
197
-
198
- const invalidCases = [
199
- { method: "POST", path: "/bad", body: Uint8Array.from([1]) },
200
- { method: "POST", path: "/bad", body: () => undefined },
201
- { method: "POST", path: "/bad", bodyType: "raw" },
202
- { method: "POST", path: "/bad", bodyType: "formUrlencoded" },
203
- { method: "POST", path: "/bad", bodyType: "multipartForm" },
204
- { method: "POST", path: "/bad", bodyType: "binary" },
205
- ];
206
- for (const options of invalidCases) {
207
- const { client, executeQuery } = createClient();
208
- await expect(
209
- callApiRequest(client, options, { response: JsonResponseSchema }),
210
- ).rejects.toThrow(RestApiValidationError);
211
- expect(executeQuery).not.toHaveBeenCalled();
212
- }
213
- });
214
- });
@@ -1,7 +0,0 @@
1
- ## Request Body Types
2
-
3
- This organization's agent does not support the `bodyType` option on `apiRequest()` yet. Its worker runs an sdk-api version that always serializes request bodies as JSON, so raw strings, binary uploads, multipart/form-data, and application/x-www-form-urlencoded payloads cannot be sent from SDK APIs until the agent is upgraded.
4
-
5
- Do not generate code that passes a `bodyType` value before that upgrade. It may typecheck against a newer local copy of the SDK but fail at runtime on this agent.
6
-
7
- When the user needs a non-JSON request body, tell them the required action: an administrator must upgrade this organization's Superblocks agent (On-Premise Agent / OPA) to a newer version that supports the `bodyType` option. Until that upgrade happens, there is no code-level workaround.
@@ -1,106 +0,0 @@
1
- ## Request Body Types
2
-
3
- `apiRequest()` serializes request bodies as JSON by default. For endpoints that expect another encoding, pass `bodyType`:
4
-
5
- - `"json"` for JSON payloads. This is the default.
6
- - `"raw"` for caller-encoded string bodies such as XML, CSV, or plain text.
7
- - `"formUrlencoded"` for `application/x-www-form-urlencoded` payloads.
8
- - `"multipartForm"` for multipart fields and file parts.
9
- - `"binary"` for byte payloads such as `Uint8Array`, `ArrayBuffer`, `DataView`, or `Buffer`.
10
-
11
- ### Form URL-Encoded Requests
12
-
13
- Use `bodyType: "formUrlencoded"` for Stripe, OAuth token exchanges, and APIs that expect HTML form encoding. Arrays repeat the key in order, and nested fields should be flattened with bracket notation:
14
-
15
- ```typescript
16
- const token = await ctx.integrations.authApi.apiRequest(
17
- {
18
- method: "POST",
19
- path: "/oauth/token",
20
- bodyType: "formUrlencoded",
21
- body: {
22
- grant_type: "client_credentials",
23
- client_id: input.clientId,
24
- scope: ["read:orders", "write:orders"],
25
- },
26
- },
27
- { response: TokenResponseSchema },
28
- );
29
-
30
- const charge = await ctx.integrations.stripe.apiRequest(
31
- {
32
- method: "POST",
33
- path: "/v1/charges",
34
- bodyType: "formUrlencoded",
35
- body: {
36
- amount: 2000,
37
- currency: "usd",
38
- "metadata[order_id]": "6735",
39
- },
40
- },
41
- { response: ChargeResponseSchema },
42
- );
43
- ```
44
-
45
- The SDK adds `Content-Type: application/x-www-form-urlencoded` unless you already provided a `Content-Type` header.
46
- Fields whose value is `undefined` are omitted. Empty arrays are omitted. The body must encode at least one field.
47
-
48
- ### Binary Uploads
49
-
50
- Use `bodyType: "binary"` for APIs that accept the request body as bytes, such as SharePoint-style upload endpoints:
51
-
52
- ```typescript
53
- await ctx.integrations.sharepoint.apiRequest(
54
- {
55
- method: "PUT",
56
- path: `/sites/${siteId}/drive/root:/reports/monthly.pdf:/content`,
57
- bodyType: "binary",
58
- body: pdfBytes,
59
- },
60
- { response: UploadResponseSchema },
61
- );
62
- ```
63
-
64
- The SDK sends the exact byte window for views such as `Uint8Array.subarray()` and `DataView`. It adds `Content-Type: application/octet-stream` unless you already provided a `Content-Type` header such as `application/pdf`.
65
- Request bodies are limited to 20 MiB before serialization so the agent request stays under its 28 MiB serialized size cap.
66
-
67
- ### Multipart Uploads
68
-
69
- Use `bodyType: "multipartForm"` for endpoints that expect fields plus file parts. File parts must be wrapped as `{ value, filename }`:
70
-
71
- ```typescript
72
- const upload = await ctx.integrations.filesApi.apiRequest(
73
- {
74
- method: "POST",
75
- path: "/files",
76
- bodyType: "multipartForm",
77
- body: {
78
- folder: "invoices",
79
- invoice: { value: invoicePdfBytes, filename: "invoice.pdf" },
80
- },
81
- },
82
- { response: UploadResponseSchema },
83
- );
84
- ```
85
-
86
- Do not set `Content-Type` for multipart requests. The worker generates the multipart boundary during execution.
87
- Do not set per-part `contentType`. Fields whose value is `undefined` are omitted. Empty file parts are allowed. The total multipart field and file-part content is limited to 20 MiB before serialization.
88
-
89
- ### Raw String Bodies
90
-
91
- Use `bodyType: "raw"` for pre-encoded text bodies. The SDK does not add a `Content-Type` header in raw mode, so provide the header expected by the API:
92
-
93
- ```typescript
94
- await ctx.integrations.legacyApi.apiRequest(
95
- {
96
- method: "POST",
97
- path: "/soap",
98
- bodyType: "raw",
99
- body: `<Envelope><Body>${payload}</Body></Envelope>`,
100
- headers: { "Content-Type": "text/xml" },
101
- },
102
- { response: SoapResponseSchema },
103
- );
104
- ```
105
-
106
- Raw string bodies are limited to 20 MiB.