@superblocksteam/sdk-api 0.0.12-body-types → 0.0.13
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.
- package/README.md +23 -0
- package/dist/errors.d.ts +36 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +231 -38
- package/dist/errors.js.map +1 -1
- package/dist/errors.test.d.ts +2 -0
- package/dist/errors.test.d.ts.map +1 -0
- package/dist/errors.test.js +189 -0
- package/dist/errors.test.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/anthropic/types.d.ts +1 -1
- package/dist/integrations/base/decode-worker-binary-response.d.ts.map +1 -1
- package/dist/integrations/base/decode-worker-binary-response.js +2 -5
- package/dist/integrations/base/decode-worker-binary-response.js.map +1 -1
- package/dist/integrations/base/index.d.ts +1 -1
- package/dist/integrations/base/index.d.ts.map +1 -1
- package/dist/integrations/base/request-body.d.ts +18 -10
- package/dist/integrations/base/request-body.d.ts.map +1 -1
- package/dist/integrations/base/request-body.js +131 -215
- package/dist/integrations/base/request-body.js.map +1 -1
- package/dist/integrations/base/request-body.test.js +306 -164
- package/dist/integrations/base/request-body.test.js.map +1 -1
- package/dist/integrations/base/rest-api-client-base.d.ts.map +1 -1
- package/dist/integrations/base/rest-api-client-base.js +13 -26
- package/dist/integrations/base/rest-api-client-base.js.map +1 -1
- package/dist/integrations/base/rest-api-integration-client.d.ts.map +1 -1
- package/dist/integrations/base/rest-api-integration-client.js +2 -5
- package/dist/integrations/base/rest-api-integration-client.js.map +1 -1
- package/dist/integrations/base/types.d.ts +0 -8
- package/dist/integrations/base/types.d.ts.map +1 -1
- package/dist/integrations/cosmosdb/client.d.ts.map +1 -1
- package/dist/integrations/cosmosdb/client.js +2 -5
- package/dist/integrations/cosmosdb/client.js.map +1 -1
- package/dist/integrations/documentation-resolver.test.js +88 -2
- package/dist/integrations/documentation-resolver.test.js.map +1 -1
- package/dist/integrations/documentation.test.js +10 -0
- package/dist/integrations/documentation.test.js.map +1 -1
- package/dist/integrations/dynamodb/client.d.ts +6 -2
- package/dist/integrations/dynamodb/client.d.ts.map +1 -1
- package/dist/integrations/dynamodb/client.js +85 -15
- package/dist/integrations/dynamodb/client.js.map +1 -1
- package/dist/integrations/dynamodb/client.test.d.ts +8 -0
- package/dist/integrations/dynamodb/client.test.d.ts.map +1 -0
- package/dist/integrations/dynamodb/client.test.js +198 -0
- package/dist/integrations/dynamodb/client.test.js.map +1 -0
- package/dist/integrations/dynamodb/index.d.ts +1 -1
- package/dist/integrations/dynamodb/index.d.ts.map +1 -1
- package/dist/integrations/dynamodb/index.js.map +1 -1
- package/dist/integrations/dynamodb/types.d.ts +27 -1
- package/dist/integrations/dynamodb/types.d.ts.map +1 -1
- package/dist/integrations/gcs/client.d.ts.map +1 -1
- package/dist/integrations/gcs/client.js +2 -5
- package/dist/integrations/gcs/client.js.map +1 -1
- package/dist/integrations/gsheets/client.d.ts.map +1 -1
- package/dist/integrations/gsheets/client.js +2 -5
- package/dist/integrations/gsheets/client.js.map +1 -1
- package/dist/integrations/index.d.ts +1 -1
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/mongodb/client.d.ts.map +1 -1
- package/dist/integrations/mongodb/client.js +2 -5
- package/dist/integrations/mongodb/client.js.map +1 -1
- package/dist/integrations/restapiintegration/client.body-types.test.js +107 -25
- package/dist/integrations/restapiintegration/client.body-types.test.js.map +1 -1
- package/dist/integrations/restapiintegration/client.test.js +16 -0
- package/dist/integrations/restapiintegration/client.test.js.map +1 -1
- package/dist/integrations/s3/client.d.ts.map +1 -1
- package/dist/integrations/s3/client.js +2 -5
- package/dist/integrations/s3/client.js.map +1 -1
- package/dist/integrations/salesforce/client.d.ts.map +1 -1
- package/dist/integrations/salesforce/client.js +2 -5
- package/dist/integrations/salesforce/client.js.map +1 -1
- package/dist/integrations/slack/client.d.ts.map +1 -1
- package/dist/integrations/slack/client.js +4 -13
- package/dist/integrations/slack/client.js.map +1 -1
- package/dist/integrations/slack/client.test.js +2 -5
- package/dist/integrations/slack/client.test.js.map +1 -1
- package/dist/integrations/utils.d.ts +8 -3
- package/dist/integrations/utils.d.ts.map +1 -1
- package/dist/integrations/utils.js +42 -1
- package/dist/integrations/utils.js.map +1 -1
- package/dist/runtime/context.d.ts +6 -0
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/context.js +2 -1
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/executor.d.ts +6 -0
- package/dist/runtime/executor.d.ts.map +1 -1
- package/dist/runtime/executor.js +1 -0
- package/dist/runtime/executor.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/errors.test.ts +257 -0
- package/src/errors.ts +289 -46
- package/src/index.ts +1 -0
- package/src/integrations/anthropic/README.md +12 -59
- package/src/integrations/anthropic/types.ts +1 -1
- package/src/integrations/base/decode-worker-binary-response.ts +5 -7
- package/src/integrations/base/index.ts +0 -5
- package/src/integrations/base/request-body.test.ts +358 -195
- package/src/integrations/base/request-body.ts +170 -326
- package/src/integrations/base/rest-api-client-base.ts +22 -31
- package/src/integrations/base/rest-api-integration-client.ts +8 -7
- package/src/integrations/base/types.ts +0 -18
- package/src/integrations/box/README.md +4 -60
- package/src/integrations/cosmosdb/client.ts +8 -7
- package/src/integrations/documentation-resolver.test.ts +108 -2
- package/src/integrations/documentation.test.ts +12 -0
- package/src/integrations/dropbox/README.md +1 -71
- package/src/integrations/dropbox/docs.manifest.json +10 -1
- package/src/integrations/dropbox/overlays/upload-unsupported.md +3 -0
- package/src/integrations/dropbox/overlays/upload.md +89 -0
- package/src/integrations/dynamodb/README.md +33 -12
- package/src/integrations/dynamodb/client.test.ts +254 -0
- package/src/integrations/dynamodb/client.ts +129 -23
- package/src/integrations/dynamodb/index.ts +5 -1
- package/src/integrations/dynamodb/types.ts +33 -1
- package/src/integrations/elasticsearch/README.md +0 -80
- package/src/integrations/elasticsearch/docs.manifest.json +10 -1
- package/src/integrations/elasticsearch/overlays/bulk-unsupported.md +3 -0
- package/src/integrations/elasticsearch/overlays/bulk.md +80 -0
- package/src/integrations/gcs/client.ts +8 -7
- package/src/integrations/googledrive/README.md +10 -36
- package/src/integrations/gsheets/client.ts +8 -7
- package/src/integrations/index.ts +1 -0
- package/src/integrations/jira/README.md +0 -26
- package/src/integrations/jira/docs.manifest.json +10 -1
- package/src/integrations/jira/overlays/attachments-unsupported.md +3 -0
- package/src/integrations/jira/overlays/attachments.md +30 -0
- package/src/integrations/mongodb/client.ts +8 -7
- package/src/integrations/restapiintegration/client.body-types.test.ts +135 -26
- package/src/integrations/restapiintegration/client.test.ts +23 -0
- package/src/integrations/restapiintegration/docs.manifest.json +2 -2
- package/src/integrations/restapiintegration/overlays/request-body-types.md +26 -17
- package/src/integrations/s3/client.ts +8 -7
- package/src/integrations/salesforce/client.ts +9 -7
- package/src/integrations/slack/client.test.ts +2 -5
- package/src/integrations/slack/client.ts +13 -19
- package/src/integrations/stabilityai/README.md +0 -87
- package/src/integrations/stabilityai/docs.manifest.json +10 -1
- package/src/integrations/stabilityai/overlays/image-uploads-unsupported.md +3 -0
- package/src/integrations/stabilityai/overlays/image-uploads.md +120 -0
- package/src/integrations/stripe/README.md +0 -201
- package/src/integrations/stripe/docs.manifest.json +10 -1
- package/src/integrations/stripe/overlays/request-bodies-unsupported.md +3 -0
- package/src/integrations/stripe/overlays/request-bodies.md +204 -0
- package/src/integrations/utils.ts +51 -1
- package/src/runtime/context.ts +9 -0
- package/src/runtime/executor.ts +8 -0
- package/src/types.ts +11 -0
|
@@ -10,57 +10,6 @@ Process payments, manage customers, and interact with Stripe's payment platform.
|
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
|
-
### Create a Customer
|
|
14
|
-
|
|
15
|
-
```typescript
|
|
16
|
-
import { api, z, stripe } from "@superblocksteam/sdk-api";
|
|
17
|
-
|
|
18
|
-
// Integration ID from the integrations panel
|
|
19
|
-
const PROD_STRIPE = "a1b2c3d4-5678-90ab-cdef-stripe000001";
|
|
20
|
-
|
|
21
|
-
const CustomerSchema = z.object({
|
|
22
|
-
id: z.string(),
|
|
23
|
-
object: z.literal("customer"),
|
|
24
|
-
email: z.string().nullable(),
|
|
25
|
-
name: z.string().nullable(),
|
|
26
|
-
created: z.number(),
|
|
27
|
-
metadata: z.record(z.string()),
|
|
28
|
-
default_source: z.string().nullable(),
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
export default api({
|
|
32
|
-
name: "StripeExample",
|
|
33
|
-
integrations: {
|
|
34
|
-
stripe: stripe(PROD_STRIPE),
|
|
35
|
-
},
|
|
36
|
-
input: z.object({
|
|
37
|
-
email: z.string().email(),
|
|
38
|
-
name: z.string(),
|
|
39
|
-
}),
|
|
40
|
-
output: z.object({
|
|
41
|
-
customerId: z.string(),
|
|
42
|
-
}),
|
|
43
|
-
async run(ctx, { email, name }) {
|
|
44
|
-
const result = await ctx.integrations.stripe.apiRequest(
|
|
45
|
-
{
|
|
46
|
-
method: "POST",
|
|
47
|
-
path: "/v1/customers",
|
|
48
|
-
body: {
|
|
49
|
-
email: email,
|
|
50
|
-
name: name,
|
|
51
|
-
metadata: {
|
|
52
|
-
source: "api",
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
{ response: CustomerSchema },
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
return { customerId: result.id };
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
```
|
|
63
|
-
|
|
64
13
|
### Get a Customer
|
|
65
14
|
|
|
66
15
|
```typescript
|
|
@@ -75,43 +24,6 @@ const customer = await ctx.integrations.stripe.apiRequest(
|
|
|
75
24
|
console.log(`Customer: ${customer.name} (${customer.email})`);
|
|
76
25
|
```
|
|
77
26
|
|
|
78
|
-
### Create a Payment Intent
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
const PaymentIntentSchema = z.object({
|
|
82
|
-
id: z.string(),
|
|
83
|
-
object: z.literal("payment_intent"),
|
|
84
|
-
amount: z.number(),
|
|
85
|
-
currency: z.string(),
|
|
86
|
-
status: z.string(),
|
|
87
|
-
client_secret: z.string(),
|
|
88
|
-
customer: z.string().nullable(),
|
|
89
|
-
metadata: z.record(z.string()),
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
const paymentIntent = await ctx.integrations.stripe.apiRequest(
|
|
93
|
-
{
|
|
94
|
-
method: "POST",
|
|
95
|
-
path: "/v1/payment_intents",
|
|
96
|
-
body: {
|
|
97
|
-
amount: 2000, // Amount in cents ($20.00)
|
|
98
|
-
currency: "usd",
|
|
99
|
-
customer: customerId,
|
|
100
|
-
automatic_payment_methods: {
|
|
101
|
-
enabled: true,
|
|
102
|
-
},
|
|
103
|
-
metadata: {
|
|
104
|
-
order_id: "order_123",
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
{ response: PaymentIntentSchema },
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
// Return client_secret to frontend for Stripe.js
|
|
112
|
-
console.log(`Client secret: ${paymentIntent.client_secret}`);
|
|
113
|
-
```
|
|
114
|
-
|
|
115
27
|
### List Charges
|
|
116
28
|
|
|
117
29
|
```typescript
|
|
@@ -151,67 +63,6 @@ charges.data.forEach((charge) => {
|
|
|
151
63
|
});
|
|
152
64
|
```
|
|
153
65
|
|
|
154
|
-
### Create a Subscription
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
const SubscriptionSchema = z.object({
|
|
158
|
-
id: z.string(),
|
|
159
|
-
object: z.literal("subscription"),
|
|
160
|
-
customer: z.string(),
|
|
161
|
-
status: z.string(), // active, past_due, canceled, etc.
|
|
162
|
-
current_period_start: z.number(),
|
|
163
|
-
current_period_end: z.number(),
|
|
164
|
-
items: z.object({
|
|
165
|
-
data: z.array(
|
|
166
|
-
z.object({
|
|
167
|
-
id: z.string(),
|
|
168
|
-
price: z.object({ id: z.string() }),
|
|
169
|
-
}),
|
|
170
|
-
),
|
|
171
|
-
}),
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
const subscription = await ctx.integrations.stripe.apiRequest(
|
|
175
|
-
{
|
|
176
|
-
method: "POST",
|
|
177
|
-
path: "/v1/subscriptions",
|
|
178
|
-
body: {
|
|
179
|
-
customer: customerId,
|
|
180
|
-
items: [{ price: "price_abc123" }],
|
|
181
|
-
payment_behavior: "default_incomplete",
|
|
182
|
-
expand: ["latest_invoice.payment_intent"],
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
{ response: SubscriptionSchema },
|
|
186
|
-
);
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### Create a Refund
|
|
190
|
-
|
|
191
|
-
```typescript
|
|
192
|
-
const RefundSchema = z.object({
|
|
193
|
-
id: z.string(),
|
|
194
|
-
object: z.literal("refund"),
|
|
195
|
-
amount: z.number(),
|
|
196
|
-
charge: z.string(),
|
|
197
|
-
status: z.string(), // succeeded, pending, failed, canceled
|
|
198
|
-
created: z.number(),
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
const refund = await ctx.integrations.stripe.apiRequest(
|
|
202
|
-
{
|
|
203
|
-
method: "POST",
|
|
204
|
-
path: "/v1/refunds",
|
|
205
|
-
body: {
|
|
206
|
-
charge: chargeId,
|
|
207
|
-
amount: 1000, // Partial refund of $10.00
|
|
208
|
-
reason: "requested_by_customer",
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
{ response: RefundSchema },
|
|
212
|
-
);
|
|
213
|
-
```
|
|
214
|
-
|
|
215
66
|
### List Products
|
|
216
67
|
|
|
217
68
|
```typescript
|
|
@@ -243,58 +94,6 @@ const products = await ctx.integrations.stripe.apiRequest(
|
|
|
243
94
|
);
|
|
244
95
|
```
|
|
245
96
|
|
|
246
|
-
### Create Invoice
|
|
247
|
-
|
|
248
|
-
```typescript
|
|
249
|
-
const InvoiceSchema = z.object({
|
|
250
|
-
id: z.string(),
|
|
251
|
-
object: z.literal("invoice"),
|
|
252
|
-
customer: z.string(),
|
|
253
|
-
status: z.string(), // draft, open, paid, uncollectible, void
|
|
254
|
-
total: z.number(),
|
|
255
|
-
amount_due: z.number(),
|
|
256
|
-
hosted_invoice_url: z.string().nullable(),
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
const invoice = await ctx.integrations.stripe.apiRequest(
|
|
260
|
-
{
|
|
261
|
-
method: "POST",
|
|
262
|
-
path: "/v1/invoices",
|
|
263
|
-
body: {
|
|
264
|
-
customer: customerId,
|
|
265
|
-
collection_method: "send_invoice",
|
|
266
|
-
days_until_due: 30,
|
|
267
|
-
},
|
|
268
|
-
},
|
|
269
|
-
{ response: InvoiceSchema },
|
|
270
|
-
);
|
|
271
|
-
|
|
272
|
-
// Add line items
|
|
273
|
-
await ctx.integrations.stripe.apiRequest(
|
|
274
|
-
{
|
|
275
|
-
method: "POST",
|
|
276
|
-
path: "/v1/invoiceitems",
|
|
277
|
-
body: {
|
|
278
|
-
customer: customerId,
|
|
279
|
-
invoice: invoice.id,
|
|
280
|
-
amount: 5000,
|
|
281
|
-
currency: "usd",
|
|
282
|
-
description: "Consulting services",
|
|
283
|
-
},
|
|
284
|
-
},
|
|
285
|
-
{ response: z.object({ id: z.string() }) },
|
|
286
|
-
);
|
|
287
|
-
|
|
288
|
-
// Finalize and send
|
|
289
|
-
await ctx.integrations.stripe.apiRequest(
|
|
290
|
-
{
|
|
291
|
-
method: "POST",
|
|
292
|
-
path: `/v1/invoices/${invoice.id}/finalize`,
|
|
293
|
-
},
|
|
294
|
-
{ response: InvoiceSchema },
|
|
295
|
-
);
|
|
296
|
-
```
|
|
297
|
-
|
|
298
97
|
## Trace Metadata
|
|
299
98
|
|
|
300
99
|
All methods accept an optional `metadata` parameter as the last argument for diagnostics labeling. See the [root SDK README](../../../README.md#trace-metadata) for details.
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"pluginId": "stripe",
|
|
3
3
|
"base": "README.md",
|
|
4
|
-
"overlays": [
|
|
4
|
+
"overlays": [
|
|
5
|
+
{
|
|
6
|
+
"file": "overlays/request-bodies.md",
|
|
7
|
+
"sdkVersionRange": ">=0.0.7"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"file": "overlays/request-bodies-unsupported.md",
|
|
11
|
+
"sdkVersionRange": "<0.0.7"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
5
14
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
## Creating Customers, Payment Intents, Subscriptions, Refunds, and Invoices
|
|
2
|
+
|
|
3
|
+
Stripe rejects any request whose body is not `application/x-www-form-urlencoded`. This agent's sdk-api cannot send that encoding through `apiRequest()` because it serializes every body as JSON, so creating a customer, payment intent, subscription, refund, or invoice always fails. Do not generate Stripe write code until the agent is upgraded. Getting a customer, listing charges, and listing products work as documented above; they send no body.
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
## Creating Customers, Payment Intents, Subscriptions, Refunds, and Invoices
|
|
2
|
+
|
|
3
|
+
Stripe expects `application/x-www-form-urlencoded` bodies, not JSON, so pass `bodyType: "formUrlencoded"` on every write request. Flatten nested fields with bracket notation, such as `"metadata[order_id]"`. An array field whose API name ends in `[]`, such as `expand`, needs the brackets in the key: `"expand[]": [...]`. The SDK adds `Content-Type: application/x-www-form-urlencoded` unless you already provided a `Content-Type` header.
|
|
4
|
+
|
|
5
|
+
### Create a Customer
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { api, z, stripe } from "@superblocksteam/sdk-api";
|
|
9
|
+
|
|
10
|
+
// Integration ID from the integrations panel
|
|
11
|
+
const PROD_STRIPE = "a1b2c3d4-5678-90ab-cdef-stripe000001";
|
|
12
|
+
|
|
13
|
+
const CustomerSchema = z.object({
|
|
14
|
+
id: z.string(),
|
|
15
|
+
object: z.literal("customer"),
|
|
16
|
+
email: z.string().nullable(),
|
|
17
|
+
name: z.string().nullable(),
|
|
18
|
+
created: z.number(),
|
|
19
|
+
metadata: z.record(z.string()),
|
|
20
|
+
default_source: z.string().nullable(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default api({
|
|
24
|
+
name: "StripeExample",
|
|
25
|
+
integrations: {
|
|
26
|
+
stripe: stripe(PROD_STRIPE),
|
|
27
|
+
},
|
|
28
|
+
input: z.object({
|
|
29
|
+
email: z.string().email(),
|
|
30
|
+
name: z.string(),
|
|
31
|
+
}),
|
|
32
|
+
output: z.object({
|
|
33
|
+
customerId: z.string(),
|
|
34
|
+
}),
|
|
35
|
+
async run(ctx, { email, name }) {
|
|
36
|
+
const result = await ctx.integrations.stripe.apiRequest(
|
|
37
|
+
{
|
|
38
|
+
method: "POST",
|
|
39
|
+
path: "/v1/customers",
|
|
40
|
+
bodyType: "formUrlencoded",
|
|
41
|
+
body: {
|
|
42
|
+
email: email,
|
|
43
|
+
name: name,
|
|
44
|
+
"metadata[source]": "api",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
{ response: CustomerSchema },
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
return { customerId: result.id };
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Create a Payment Intent
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
const PaymentIntentSchema = z.object({
|
|
59
|
+
id: z.string(),
|
|
60
|
+
object: z.literal("payment_intent"),
|
|
61
|
+
amount: z.number(),
|
|
62
|
+
currency: z.string(),
|
|
63
|
+
status: z.string(),
|
|
64
|
+
client_secret: z.string(),
|
|
65
|
+
customer: z.string().nullable(),
|
|
66
|
+
metadata: z.record(z.string()),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const paymentIntent = await ctx.integrations.stripe.apiRequest(
|
|
70
|
+
{
|
|
71
|
+
method: "POST",
|
|
72
|
+
path: "/v1/payment_intents",
|
|
73
|
+
bodyType: "formUrlencoded",
|
|
74
|
+
body: {
|
|
75
|
+
amount: 2000, // Amount in cents ($20.00)
|
|
76
|
+
currency: "usd",
|
|
77
|
+
customer: customerId,
|
|
78
|
+
"automatic_payment_methods[enabled]": true,
|
|
79
|
+
"metadata[order_id]": "order_123",
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{ response: PaymentIntentSchema },
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// Return client_secret to frontend for Stripe.js
|
|
86
|
+
console.log(`Client secret: ${paymentIntent.client_secret}`);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Create a Subscription
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
const SubscriptionSchema = z.object({
|
|
93
|
+
id: z.string(),
|
|
94
|
+
object: z.literal("subscription"),
|
|
95
|
+
customer: z.string(),
|
|
96
|
+
status: z.string(), // active, past_due, canceled, etc.
|
|
97
|
+
current_period_start: z.number(),
|
|
98
|
+
current_period_end: z.number(),
|
|
99
|
+
items: z.object({
|
|
100
|
+
data: z.array(
|
|
101
|
+
z.object({
|
|
102
|
+
id: z.string(),
|
|
103
|
+
price: z.object({ id: z.string() }),
|
|
104
|
+
}),
|
|
105
|
+
),
|
|
106
|
+
}),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const subscription = await ctx.integrations.stripe.apiRequest(
|
|
110
|
+
{
|
|
111
|
+
method: "POST",
|
|
112
|
+
path: "/v1/subscriptions",
|
|
113
|
+
bodyType: "formUrlencoded",
|
|
114
|
+
body: {
|
|
115
|
+
customer: customerId,
|
|
116
|
+
"items[0][price]": "price_abc123",
|
|
117
|
+
payment_behavior: "default_incomplete",
|
|
118
|
+
"expand[]": ["latest_invoice.payment_intent"],
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
{ response: SubscriptionSchema },
|
|
122
|
+
);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Create a Refund
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
const RefundSchema = z.object({
|
|
129
|
+
id: z.string(),
|
|
130
|
+
object: z.literal("refund"),
|
|
131
|
+
amount: z.number(),
|
|
132
|
+
charge: z.string(),
|
|
133
|
+
status: z.string(), // succeeded, pending, failed, canceled
|
|
134
|
+
created: z.number(),
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const refund = await ctx.integrations.stripe.apiRequest(
|
|
138
|
+
{
|
|
139
|
+
method: "POST",
|
|
140
|
+
path: "/v1/refunds",
|
|
141
|
+
bodyType: "formUrlencoded",
|
|
142
|
+
body: {
|
|
143
|
+
charge: chargeId,
|
|
144
|
+
amount: 1000, // Partial refund of $10.00
|
|
145
|
+
reason: "requested_by_customer",
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
{ response: RefundSchema },
|
|
149
|
+
);
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Create Invoice
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const InvoiceSchema = z.object({
|
|
156
|
+
id: z.string(),
|
|
157
|
+
object: z.literal("invoice"),
|
|
158
|
+
customer: z.string(),
|
|
159
|
+
status: z.string(), // draft, open, paid, uncollectible, void
|
|
160
|
+
total: z.number(),
|
|
161
|
+
amount_due: z.number(),
|
|
162
|
+
hosted_invoice_url: z.string().nullable(),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const invoice = await ctx.integrations.stripe.apiRequest(
|
|
166
|
+
{
|
|
167
|
+
method: "POST",
|
|
168
|
+
path: "/v1/invoices",
|
|
169
|
+
bodyType: "formUrlencoded",
|
|
170
|
+
body: {
|
|
171
|
+
customer: customerId,
|
|
172
|
+
collection_method: "send_invoice",
|
|
173
|
+
days_until_due: 30,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
{ response: InvoiceSchema },
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
// Add line items
|
|
180
|
+
await ctx.integrations.stripe.apiRequest(
|
|
181
|
+
{
|
|
182
|
+
method: "POST",
|
|
183
|
+
path: "/v1/invoiceitems",
|
|
184
|
+
bodyType: "formUrlencoded",
|
|
185
|
+
body: {
|
|
186
|
+
customer: customerId,
|
|
187
|
+
invoice: invoice.id,
|
|
188
|
+
amount: 5000,
|
|
189
|
+
currency: "usd",
|
|
190
|
+
description: "Consulting services",
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
{ response: z.object({ id: z.string() }) },
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
// Finalize and send; this call has no body
|
|
197
|
+
await ctx.integrations.stripe.apiRequest(
|
|
198
|
+
{
|
|
199
|
+
method: "POST",
|
|
200
|
+
path: `/v1/invoices/${invoice.id}/finalize`,
|
|
201
|
+
},
|
|
202
|
+
{ response: InvoiceSchema },
|
|
203
|
+
);
|
|
204
|
+
```
|
|
@@ -1,7 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import { isBinaryData, RestApiValidationError } from "../errors.js";
|
|
4
|
+
|
|
5
|
+
const MAX_OPTION_VALUE_CHARS = 64;
|
|
6
|
+
|
|
1
7
|
/**
|
|
2
8
|
* Integration utility functions.
|
|
3
9
|
*/
|
|
4
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Truncates a string to at most `max` characters, appending "..." when it
|
|
13
|
+
* was cut. The single place that defines how caller-supplied strings are
|
|
14
|
+
* bounded for display (`describeType`, `describeOptionValue`) and for the
|
|
15
|
+
* Zod issue `path` (`boundedPathSegment`).
|
|
16
|
+
*/
|
|
17
|
+
function truncate(value: string, max = MAX_OPTION_VALUE_CHARS): string {
|
|
18
|
+
return value.length > max ? `${value.slice(0, max)}...` : value;
|
|
19
|
+
}
|
|
20
|
+
|
|
5
21
|
/**
|
|
6
22
|
* Produces a safe, human-readable description of a value's type
|
|
7
23
|
* without exposing potentially sensitive data.
|
|
@@ -18,8 +34,42 @@ export function describeType(value: unknown): string {
|
|
|
18
34
|
if (t === "object") {
|
|
19
35
|
const keys = Object.keys(value as Record<string, unknown>);
|
|
20
36
|
if (keys.length === 0) return "empty object";
|
|
21
|
-
|
|
37
|
+
const shown = keys.slice(0, 5).map((k) => truncate(k));
|
|
38
|
+
return `object with keys [${shown.join(", ")}${keys.length > 5 ? ", ..." : ""}]`;
|
|
22
39
|
}
|
|
23
40
|
|
|
24
41
|
return t;
|
|
25
42
|
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Describes a caller-supplied option value for an error message with bounded
|
|
46
|
+
* length. Strings are quoted and truncated; everything else is described by type
|
|
47
|
+
* so arbitrary payloads never land in the message.
|
|
48
|
+
*/
|
|
49
|
+
export function describeOptionValue(value: unknown): string {
|
|
50
|
+
if (isBinaryData(value)) {
|
|
51
|
+
return `binary data (${value.byteLength} bytes)`;
|
|
52
|
+
}
|
|
53
|
+
if (typeof value !== "string") return describeType(value);
|
|
54
|
+
return JSON.stringify(truncate(value));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function boundedPathSegment(segment: string | number): string | number {
|
|
58
|
+
return typeof segment === "string" ? truncate(segment) : segment;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function validationError(
|
|
62
|
+
message: string,
|
|
63
|
+
path: (string | number)[],
|
|
64
|
+
): RestApiValidationError {
|
|
65
|
+
return new RestApiValidationError(message, {
|
|
66
|
+
data: undefined,
|
|
67
|
+
zodError: new z.ZodError([
|
|
68
|
+
{
|
|
69
|
+
code: z.ZodIssueCode.custom,
|
|
70
|
+
message,
|
|
71
|
+
path: path.map(boundedPathSegment),
|
|
72
|
+
},
|
|
73
|
+
]),
|
|
74
|
+
});
|
|
75
|
+
}
|
package/src/runtime/context.ts
CHANGED
|
@@ -57,6 +57,13 @@ export interface CreateContextOptions {
|
|
|
57
57
|
/** Environment variables */
|
|
58
58
|
env: Record<string, string>;
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Server-resolved data tag key.
|
|
62
|
+
*
|
|
63
|
+
* Optional for compatibility with execution wrappers from older agents.
|
|
64
|
+
*/
|
|
65
|
+
dataTag?: string;
|
|
66
|
+
|
|
60
67
|
/** User information from JWT */
|
|
61
68
|
user: ApiUser;
|
|
62
69
|
|
|
@@ -101,6 +108,7 @@ export function createApiContext(
|
|
|
101
108
|
executeQuery,
|
|
102
109
|
executionId,
|
|
103
110
|
env,
|
|
111
|
+
dataTag,
|
|
104
112
|
user,
|
|
105
113
|
logger,
|
|
106
114
|
} = options;
|
|
@@ -172,6 +180,7 @@ export function createApiContext(
|
|
|
172
180
|
>["integrations"],
|
|
173
181
|
log,
|
|
174
182
|
env: Object.freeze({ ...env }),
|
|
183
|
+
dataTag,
|
|
175
184
|
user,
|
|
176
185
|
};
|
|
177
186
|
}
|
package/src/runtime/executor.ts
CHANGED
|
@@ -36,6 +36,13 @@ export interface ExecuteApiRequest {
|
|
|
36
36
|
/** Environment variables available to the API */
|
|
37
37
|
env: Record<string, string>;
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Server-resolved data tag key for this execution.
|
|
41
|
+
*
|
|
42
|
+
* Optional on the low-level request for compatibility with older runtimes.
|
|
43
|
+
*/
|
|
44
|
+
dataTag?: string;
|
|
45
|
+
|
|
39
46
|
/** User information extracted from the Superblocks JWT */
|
|
40
47
|
user: ApiUser;
|
|
41
48
|
|
|
@@ -162,6 +169,7 @@ export async function executeApi<TInput = unknown, TOutput = unknown>(
|
|
|
162
169
|
executeQuery: request.executeQuery,
|
|
163
170
|
executionId: request.executionId,
|
|
164
171
|
env: request.env,
|
|
172
|
+
dataTag: request.dataTag,
|
|
165
173
|
user: request.user,
|
|
166
174
|
});
|
|
167
175
|
|
package/src/types.ts
CHANGED
|
@@ -182,6 +182,17 @@ export interface ApiContext<
|
|
|
182
182
|
/** Access to environment variables */
|
|
183
183
|
readonly env: Readonly<Record<string, string>>;
|
|
184
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Canonical key of the requested data tag validated for this execution.
|
|
187
|
+
*
|
|
188
|
+
* This identifies the integration configuration in use, not a user's
|
|
189
|
+
* environment entitlement. It is supplied by the Superblocks runtime and
|
|
190
|
+
* cannot be selected through API input. It is undefined when no data tag was
|
|
191
|
+
* resolved or on runtimes that predate data-tag context support;
|
|
192
|
+
* authorization checks must deny access in those cases.
|
|
193
|
+
*/
|
|
194
|
+
readonly dataTag?: string;
|
|
195
|
+
|
|
185
196
|
/** User information from the Superblocks JWT */
|
|
186
197
|
readonly user: ApiUser;
|
|
187
198
|
}
|