commerceforai 0.0.0-stage → 0.1.0
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 +39 -2
- package/dist/cart-core.d.ts +90 -0
- package/dist/cart-core.js +122 -0
- package/dist/checkout-handler.d.ts +26 -0
- package/dist/checkout-handler.js +63 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +216 -0
- package/dist/index.d.ts +761 -0
- package/dist/index.js +526 -0
- package/dist/react.d.ts +85 -0
- package/dist/react.js +162 -0
- package/dist/types.d.ts +530 -0
- package/dist/types.js +1 -0
- package/package.json +54 -3
- package/templates/nextjs/app/shop/[id]/page.tsx +44 -0
- package/templates/nextjs/app/shop/actions.ts +67 -0
- package/templates/nextjs/app/shop/cart/page.tsx +51 -0
- package/templates/nextjs/app/shop/cart-cookie.ts +22 -0
- package/templates/nextjs/app/shop/layout.tsx +25 -0
- package/templates/nextjs/app/shop/orders/lookup-form.tsx +32 -0
- package/templates/nextjs/app/shop/orders/page.tsx +13 -0
- package/templates/nextjs/app/shop/page.tsx +31 -0
- package/templates/nextjs/app/shop/shop.css +31 -0
- package/templates/nextjs/app/shop/thanks/clear-cart.tsx +10 -0
- package/templates/nextjs/app/shop/thanks/page.tsx +47 -0
- package/templates/nextjs/lib/commerce.ts +12 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,761 @@
|
|
|
1
|
+
import type { Collection, CollectionParams, Customer, CustomerDetail, Discount, DiscountParams, SalesReport, Checkout, CheckoutCreateParams, Dimensions, Email, Event, EventType, Label, List, Order, OrderStatus, Parcel, Product, ProductCreateParams, ProductUpdateParams, Result, Return, ShipFromAddress, ShippingRate, Store, StorefrontConfig, Variant, VariantInput, VariantUpdateParams, WebhookEndpoint } from "./types.js";
|
|
2
|
+
export type * from "./types.js";
|
|
3
|
+
export interface CommerceOptions {
|
|
4
|
+
/** Defaults to COMMERCEFORAI_BASE_URL, then https://api.commerceforai.com. */
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
/** Retries for network errors, 429 and 5xx. POSTs are retried with the same Idempotency-Key. Default 2. */
|
|
7
|
+
maxRetries?: number;
|
|
8
|
+
/** Custom fetch (e.g. for testing or proxies). */
|
|
9
|
+
fetch?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
10
|
+
}
|
|
11
|
+
type Query = Record<string, string | number | boolean | undefined>;
|
|
12
|
+
/**
|
|
13
|
+
* ```ts
|
|
14
|
+
* const commerce = new Commerce(process.env.COMMERCEFORAI_API_KEY);
|
|
15
|
+
* const { data, error } = await commerce.checkouts.create({ items: [{ variant_id, quantity: 1 }], success_url });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare class Commerce {
|
|
19
|
+
readonly products: Products;
|
|
20
|
+
readonly variants: Variants;
|
|
21
|
+
readonly inventory: InventoryResource;
|
|
22
|
+
readonly checkouts: Checkouts;
|
|
23
|
+
readonly orders: Orders;
|
|
24
|
+
readonly events: Events;
|
|
25
|
+
readonly webhooks: Webhooks;
|
|
26
|
+
readonly store: StoreResource;
|
|
27
|
+
readonly returns: Returns;
|
|
28
|
+
readonly emails: Emails;
|
|
29
|
+
readonly collections: Collections;
|
|
30
|
+
readonly customers: Customers;
|
|
31
|
+
readonly discounts: Discounts;
|
|
32
|
+
readonly reports: Reports;
|
|
33
|
+
readonly printify: PrintifyResource;
|
|
34
|
+
readonly files: Files;
|
|
35
|
+
private readonly key;
|
|
36
|
+
private readonly baseUrl;
|
|
37
|
+
private readonly maxRetries;
|
|
38
|
+
private readonly fetchImpl;
|
|
39
|
+
constructor(apiKey?: string, opts?: CommerceOptions);
|
|
40
|
+
/** @internal */
|
|
41
|
+
request<T>(method: "GET" | "POST" | "PATCH" | "PUT" | "DELETE", path: string, opts?: {
|
|
42
|
+
body?: unknown;
|
|
43
|
+
query?: Query;
|
|
44
|
+
idempotencyKey?: string;
|
|
45
|
+
}): Promise<Result<T>>;
|
|
46
|
+
}
|
|
47
|
+
declare abstract class Resource {
|
|
48
|
+
protected readonly client: Commerce;
|
|
49
|
+
constructor(client: Commerce);
|
|
50
|
+
}
|
|
51
|
+
declare class Products extends Resource {
|
|
52
|
+
/**
|
|
53
|
+
* Create up to 100 products in one request. Each succeeds or fails on its own; retry only the failures.
|
|
54
|
+
* Returns { created, failed, results: [{ index, product } | { index, error }] }.
|
|
55
|
+
*/
|
|
56
|
+
createMany(products: ProductCreateParams[]): Promise<Result<{
|
|
57
|
+
object: "bulk_result";
|
|
58
|
+
created: number;
|
|
59
|
+
failed: number;
|
|
60
|
+
results: ({
|
|
61
|
+
index: number;
|
|
62
|
+
product: Product;
|
|
63
|
+
} | {
|
|
64
|
+
index: number;
|
|
65
|
+
error: {
|
|
66
|
+
type: string;
|
|
67
|
+
message: string;
|
|
68
|
+
param?: string;
|
|
69
|
+
};
|
|
70
|
+
})[];
|
|
71
|
+
}>>;
|
|
72
|
+
/** Create a product. Use `price` for a single-variant product, or `variants` for sizes/colors. */
|
|
73
|
+
create(params: ProductCreateParams, opts?: {
|
|
74
|
+
idempotencyKey?: string;
|
|
75
|
+
}): Promise<Result<Product>>;
|
|
76
|
+
get(id: string): Promise<Result<Product>>;
|
|
77
|
+
/** `metadata` filters on exact matches, e.g. { collection: "yosemite" }. */
|
|
78
|
+
/** `q` searches product names and SKUs. */
|
|
79
|
+
list(params?: {
|
|
80
|
+
limit?: number;
|
|
81
|
+
starting_after?: string;
|
|
82
|
+
active?: boolean;
|
|
83
|
+
q?: string;
|
|
84
|
+
metadata?: Record<string, string>; /** Collection id or handle. */
|
|
85
|
+
collection?: string;
|
|
86
|
+
}): Promise<Result<List<Product>>>;
|
|
87
|
+
update(id: string, params: ProductUpdateParams): Promise<Result<Product>>;
|
|
88
|
+
/** Archive: hides it from sale; existing orders are unaffected. */
|
|
89
|
+
archive(id: string): Promise<Result<Product>>;
|
|
90
|
+
addVariant(productId: string, params: VariantInput): Promise<Result<Variant>>;
|
|
91
|
+
}
|
|
92
|
+
declare class Variants extends Resource {
|
|
93
|
+
update(id: string, params: VariantUpdateParams): Promise<Result<Variant>>;
|
|
94
|
+
}
|
|
95
|
+
declare class InventoryResource extends Resource {
|
|
96
|
+
/** Tracked variants, lowest stock first. */
|
|
97
|
+
list(params?: {
|
|
98
|
+
low_stock_threshold?: number;
|
|
99
|
+
}): Promise<Result<List<Variant & {
|
|
100
|
+
product_name: string;
|
|
101
|
+
}>>>;
|
|
102
|
+
/** Add/remove units, e.g. `{ adjust: 50 }` after a restock or `{ adjust: -1 }` for damage. */
|
|
103
|
+
adjust(variantId: string, adjust: number, reason?: string): Promise<Result<Variant>>;
|
|
104
|
+
/** Set the absolute on-hand count, e.g. after a stock count. */
|
|
105
|
+
set(variantId: string, onHand: number, reason?: string): Promise<Result<Variant>>;
|
|
106
|
+
}
|
|
107
|
+
declare class Checkouts extends Resource {
|
|
108
|
+
/** Reserve stock and create a Stripe-hosted checkout. Redirect the customer to `data.url`. */
|
|
109
|
+
create(params: CheckoutCreateParams, opts?: {
|
|
110
|
+
idempotencyKey?: string;
|
|
111
|
+
}): Promise<Result<Checkout>>;
|
|
112
|
+
get(id: string): Promise<Result<Checkout>>;
|
|
113
|
+
}
|
|
114
|
+
declare class Orders extends Resource {
|
|
115
|
+
/** `q` matches an order number, customer email or name. */
|
|
116
|
+
list(params?: {
|
|
117
|
+
limit?: number;
|
|
118
|
+
starting_after?: string;
|
|
119
|
+
status?: OrderStatus | OrderStatus[];
|
|
120
|
+
q?: string;
|
|
121
|
+
}): Promise<Result<List<Order>>>;
|
|
122
|
+
/** Accepts an order id (`ord_...`) or order number (`1001`). */
|
|
123
|
+
get(idOrNumber: string | number): Promise<Result<Order>>;
|
|
124
|
+
update(id: string | number, params: {
|
|
125
|
+
note?: string | null;
|
|
126
|
+
metadata?: Record<string, string>;
|
|
127
|
+
}): Promise<Result<Order>>;
|
|
128
|
+
/** Mark shipped. Calling again updates tracking. */
|
|
129
|
+
fulfill(id: string | number, params?: {
|
|
130
|
+
carrier?: string;
|
|
131
|
+
tracking_number?: string;
|
|
132
|
+
tracking_url?: string;
|
|
133
|
+
}): Promise<Result<Order>>;
|
|
134
|
+
/**
|
|
135
|
+
* Get live label rates from your EasyPost/Shippo account, cheapest first.
|
|
136
|
+
* Parcel weight defaults to the sum of variant `weight_oz`. Pass `return_id` for return-label rates.
|
|
137
|
+
*/
|
|
138
|
+
shippingRates(id: string | number, params?: {
|
|
139
|
+
parcel?: Parcel;
|
|
140
|
+
return_id?: string;
|
|
141
|
+
}): Promise<Result<List<ShippingRate> & {
|
|
142
|
+
parcel: Required<Parcel>;
|
|
143
|
+
}>>;
|
|
144
|
+
/** Buy a label for a rate. Outbound labels also mark the order fulfilled with tracking (and email the customer). */
|
|
145
|
+
buyLabel(id: string | number, rateId: string, opts?: {
|
|
146
|
+
max_cost?: number;
|
|
147
|
+
}): Promise<Result<Label>>;
|
|
148
|
+
/** Send a paid order to the print-on-demand provider now (e.g. after fixing a missing print file). */
|
|
149
|
+
submitFulfillment(id: string | number, params?: {
|
|
150
|
+
provider?: "printful" | "printify";
|
|
151
|
+
}): Promise<Result<Order>>;
|
|
152
|
+
labels(id: string | number): Promise<Result<List<Label>>>;
|
|
153
|
+
/** Refund through Stripe. Omit `amount` for a full refund; `restock` returns items to inventory. */
|
|
154
|
+
refund(id: string | number, params?: {
|
|
155
|
+
amount?: number;
|
|
156
|
+
restock?: boolean;
|
|
157
|
+
reason?: "duplicate" | "fraudulent" | "requested_by_customer";
|
|
158
|
+
}): Promise<Result<Order>>;
|
|
159
|
+
}
|
|
160
|
+
declare class Collections extends Resource {
|
|
161
|
+
/** Group products, e.g. { name: "Mugs", product_ids: [...] }. The handle defaults from the name. */
|
|
162
|
+
create(params: CollectionParams & {
|
|
163
|
+
name: string;
|
|
164
|
+
}): Promise<Result<Collection>>;
|
|
165
|
+
list(): Promise<Result<List<Collection>>>;
|
|
166
|
+
/** By id or handle. */
|
|
167
|
+
get(idOrHandle: string): Promise<Result<Collection>>;
|
|
168
|
+
/** Passing product_ids replaces the membership (in that order). */
|
|
169
|
+
update(idOrHandle: string, params: CollectionParams): Promise<Result<Collection>>;
|
|
170
|
+
addProducts(idOrHandle: string, productIds: string[]): Promise<Result<Collection>>;
|
|
171
|
+
removeProduct(idOrHandle: string, productId: string): Promise<Result<Collection>>;
|
|
172
|
+
delete(idOrHandle: string): Promise<Result<{
|
|
173
|
+
id: string;
|
|
174
|
+
deleted: true;
|
|
175
|
+
}>>;
|
|
176
|
+
}
|
|
177
|
+
declare class Customers extends Resource {
|
|
178
|
+
/** Everyone who has paid, matched by email. Search by email or name; sort by recent (default), spent or orders. */
|
|
179
|
+
list(params?: {
|
|
180
|
+
q?: string;
|
|
181
|
+
sort?: "recent" | "spent" | "orders";
|
|
182
|
+
limit?: number;
|
|
183
|
+
page?: number;
|
|
184
|
+
}): Promise<Result<List<Customer> & {
|
|
185
|
+
page: number;
|
|
186
|
+
}>>;
|
|
187
|
+
/** Totals, last address and full order history for one email. */
|
|
188
|
+
get(email: string): Promise<Result<CustomerDetail>>;
|
|
189
|
+
}
|
|
190
|
+
declare class Discounts extends Resource {
|
|
191
|
+
/** e.g. { code: "SUMMER20", kind: "percent", value: 20 } or { code: "FIVEOFF", kind: "amount", value: 500 }. */
|
|
192
|
+
create(params: DiscountParams): Promise<Result<Discount>>;
|
|
193
|
+
list(): Promise<Result<List<Discount>>>;
|
|
194
|
+
/** By id or code. */
|
|
195
|
+
get(idOrCode: string): Promise<Result<Discount>>;
|
|
196
|
+
update(idOrCode: string, params: Partial<DiscountParams>): Promise<Result<Discount>>;
|
|
197
|
+
delete(idOrCode: string): Promise<Result<{
|
|
198
|
+
id: string;
|
|
199
|
+
deleted: true;
|
|
200
|
+
}>>;
|
|
201
|
+
}
|
|
202
|
+
declare class Reports extends Resource {
|
|
203
|
+
/** Sales over the last `days` (default 30, max 366): totals vs the previous period, a time series and top products. */
|
|
204
|
+
sales(params?: {
|
|
205
|
+
days?: number;
|
|
206
|
+
}): Promise<Result<SalesReport>>;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Printify, through the shop the store connected (your agent never needs the Printify token).
|
|
210
|
+
* Find a blueprint → a print provider → its variants, then create the product in Printify.
|
|
211
|
+
*/
|
|
212
|
+
declare class PrintifyResource extends Resource {
|
|
213
|
+
/** Search Printify's catalog, e.g. blueprints({ q: "heavy cotton tee" }). */
|
|
214
|
+
blueprints(params?: {
|
|
215
|
+
q?: string;
|
|
216
|
+
limit?: number;
|
|
217
|
+
}): Promise<Result<{
|
|
218
|
+
object: "list";
|
|
219
|
+
data: {
|
|
220
|
+
id: number;
|
|
221
|
+
title: string;
|
|
222
|
+
brand: string;
|
|
223
|
+
model: string;
|
|
224
|
+
images: string[];
|
|
225
|
+
}[];
|
|
226
|
+
total: number;
|
|
227
|
+
}>>;
|
|
228
|
+
providers(blueprintId: number): Promise<Result<{
|
|
229
|
+
object: "list";
|
|
230
|
+
data: {
|
|
231
|
+
id: number;
|
|
232
|
+
title: string;
|
|
233
|
+
location: unknown;
|
|
234
|
+
}[];
|
|
235
|
+
}>>;
|
|
236
|
+
/** Variant ids per size/color, the option values, and the print placements ("front", "back"…). */
|
|
237
|
+
variants(blueprintId: number, providerId: number): Promise<Result<{
|
|
238
|
+
object: "printify_variants";
|
|
239
|
+
options: Record<string, string[]>;
|
|
240
|
+
data: {
|
|
241
|
+
id: number;
|
|
242
|
+
title: string;
|
|
243
|
+
options: Record<string, string>;
|
|
244
|
+
placements: {
|
|
245
|
+
position: string;
|
|
246
|
+
width: number;
|
|
247
|
+
height: number;
|
|
248
|
+
}[];
|
|
249
|
+
}[];
|
|
250
|
+
}>>;
|
|
251
|
+
/**
|
|
252
|
+
* Create a CommerceForAI product in your Printify shop (artwork uploaded, variants priced, mockups made) and map
|
|
253
|
+
* its variants so paid orders go to production. Variants are matched by option values; pass fixed_options for
|
|
254
|
+
* options yours don't have (e.g. { color: "Black" }), or variant_map to map explicitly.
|
|
255
|
+
*/
|
|
256
|
+
createProduct(productId: string, params: {
|
|
257
|
+
blueprint_id: number;
|
|
258
|
+
print_provider_id: number;
|
|
259
|
+
print_files?: {
|
|
260
|
+
placement: string;
|
|
261
|
+
url: string;
|
|
262
|
+
}[];
|
|
263
|
+
fixed_options?: Record<string, string>;
|
|
264
|
+
variant_map?: Record<string, number>;
|
|
265
|
+
use_mockups?: boolean;
|
|
266
|
+
}): Promise<Result<{
|
|
267
|
+
object: "printify_product";
|
|
268
|
+
printify_product_id: string;
|
|
269
|
+
mockups: string[];
|
|
270
|
+
product: Product;
|
|
271
|
+
}>>;
|
|
272
|
+
}
|
|
273
|
+
export interface HostedFile {
|
|
274
|
+
object: "file";
|
|
275
|
+
id: string;
|
|
276
|
+
/** Permanent public URL on cdn.commerceforai.com. */
|
|
277
|
+
url: string;
|
|
278
|
+
filename: string | null;
|
|
279
|
+
content_type: "image/png" | "image/jpeg" | "image/webp";
|
|
280
|
+
bytes: number;
|
|
281
|
+
width: number | null;
|
|
282
|
+
height: number | null;
|
|
283
|
+
source_url: string | null;
|
|
284
|
+
created_at: string;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Image hosting (product photos, logos, print files): PNG, JPEG or WebP up to 25 MB, 5 GB per store.
|
|
288
|
+
* Photo metadata is removed; the same image is stored once; URLs never change.
|
|
289
|
+
*/
|
|
290
|
+
declare class Files extends Resource {
|
|
291
|
+
/**
|
|
292
|
+
* Upload bytes (Blob, File, Buffer, Uint8Array) or copy from a link.
|
|
293
|
+
* ```ts
|
|
294
|
+
* await commerce.files.upload(readFileSync("art/half-dome.png"), { filename: "half-dome.png" });
|
|
295
|
+
* await commerce.files.upload({ url: "https://example.com/photo.jpg" });
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
upload(input: Blob | ArrayBuffer | Uint8Array | {
|
|
299
|
+
url: string;
|
|
300
|
+
}, opts?: {
|
|
301
|
+
filename?: string;
|
|
302
|
+
}): Promise<Result<HostedFile>>;
|
|
303
|
+
list(params?: {
|
|
304
|
+
limit?: number;
|
|
305
|
+
starting_after?: string;
|
|
306
|
+
}): Promise<Result<List<HostedFile> & {
|
|
307
|
+
usage: {
|
|
308
|
+
bytes: number;
|
|
309
|
+
files: number;
|
|
310
|
+
quota_bytes: number;
|
|
311
|
+
};
|
|
312
|
+
}>>;
|
|
313
|
+
delete(id: string): Promise<Result<{
|
|
314
|
+
id: string;
|
|
315
|
+
deleted: true;
|
|
316
|
+
}>>;
|
|
317
|
+
/**
|
|
318
|
+
* Copy products' outside images (and print files) onto the CDN so a moved or deleted source can't break the store.
|
|
319
|
+
*/
|
|
320
|
+
copyProductImages(productId: string): Promise<Result<{
|
|
321
|
+
product_id: string;
|
|
322
|
+
copied: number;
|
|
323
|
+
errors: {
|
|
324
|
+
url: string;
|
|
325
|
+
message: string;
|
|
326
|
+
}[];
|
|
327
|
+
}>>;
|
|
328
|
+
/** The same for every product with outside images, up to `limit` (≤50) per call. Repeat until `remaining` is 0. */
|
|
329
|
+
copyAllProductImages(opts?: {
|
|
330
|
+
limit?: number;
|
|
331
|
+
}): Promise<Result<{
|
|
332
|
+
processed: number;
|
|
333
|
+
copied: number;
|
|
334
|
+
remaining: number;
|
|
335
|
+
errors: {
|
|
336
|
+
product_id: string;
|
|
337
|
+
url: string;
|
|
338
|
+
message: string;
|
|
339
|
+
}[];
|
|
340
|
+
}>>;
|
|
341
|
+
}
|
|
342
|
+
declare class Returns extends Resource {
|
|
343
|
+
/** Open a return for items on a shipped order. */
|
|
344
|
+
create(orderId: string | number, params: {
|
|
345
|
+
items: {
|
|
346
|
+
variant_id: string;
|
|
347
|
+
quantity: number;
|
|
348
|
+
}[];
|
|
349
|
+
reason?: string;
|
|
350
|
+
}): Promise<Result<Return>>;
|
|
351
|
+
list(params?: {
|
|
352
|
+
status?: Return["status"];
|
|
353
|
+
order_id?: string | number;
|
|
354
|
+
limit?: number;
|
|
355
|
+
}): Promise<Result<List<Return>>>;
|
|
356
|
+
get(id: string): Promise<Result<Return>>;
|
|
357
|
+
/** Approve. `return_label: "cheapest"` buys a prepaid return label and includes it in the customer email. */
|
|
358
|
+
approve(id: string, params?: {
|
|
359
|
+
return_label?: "cheapest" | {
|
|
360
|
+
rate_id: string;
|
|
361
|
+
};
|
|
362
|
+
note?: string;
|
|
363
|
+
}): Promise<Result<Return>>;
|
|
364
|
+
reject(id: string, params?: {
|
|
365
|
+
note?: string;
|
|
366
|
+
}): Promise<Result<Return>>;
|
|
367
|
+
/** Items arrived: restock (default true) and refund their value (default true; shipping not included). */
|
|
368
|
+
receive(id: string, params?: {
|
|
369
|
+
restock?: boolean;
|
|
370
|
+
refund?: boolean;
|
|
371
|
+
refund_amount?: number;
|
|
372
|
+
}): Promise<Result<Return>>;
|
|
373
|
+
}
|
|
374
|
+
declare class Emails extends Resource {
|
|
375
|
+
/** Log of customer emails sent (or queued) for your store. */
|
|
376
|
+
list(params?: {
|
|
377
|
+
order_id?: string | number;
|
|
378
|
+
}): Promise<Result<List<Email>>>;
|
|
379
|
+
/** Render a customer email with your branding and sample data. Templates: order_confirmation, order_shipped, order_refunded, return_approved, checkout_recovery. */
|
|
380
|
+
preview(template: EmailTemplate): Promise<Result<{
|
|
381
|
+
template: EmailTemplate;
|
|
382
|
+
subject: string;
|
|
383
|
+
html: string;
|
|
384
|
+
text: string;
|
|
385
|
+
}>>;
|
|
386
|
+
/** Send previews to the store owner (or the signed-in member): one template, or "all". */
|
|
387
|
+
sendTest(params?: {
|
|
388
|
+
template?: EmailTemplate | "all";
|
|
389
|
+
}): Promise<Result<{
|
|
390
|
+
sent: number;
|
|
391
|
+
to: string;
|
|
392
|
+
templates: EmailTemplate[];
|
|
393
|
+
}>>;
|
|
394
|
+
}
|
|
395
|
+
export interface StoreSyncPlan {
|
|
396
|
+
object: "sync_plan";
|
|
397
|
+
plan_id: string;
|
|
398
|
+
has_changes: boolean;
|
|
399
|
+
direction: "test_to_live" | "live_to_test";
|
|
400
|
+
source: {
|
|
401
|
+
id: string;
|
|
402
|
+
name: string;
|
|
403
|
+
mode: string;
|
|
404
|
+
};
|
|
405
|
+
destination: {
|
|
406
|
+
id: string;
|
|
407
|
+
name: string;
|
|
408
|
+
mode: string;
|
|
409
|
+
};
|
|
410
|
+
products: {
|
|
411
|
+
create: {
|
|
412
|
+
source_id: string;
|
|
413
|
+
name: string;
|
|
414
|
+
variants: number;
|
|
415
|
+
}[];
|
|
416
|
+
update: {
|
|
417
|
+
id: string;
|
|
418
|
+
name: string;
|
|
419
|
+
fields: string[];
|
|
420
|
+
new_variants: number;
|
|
421
|
+
updated_variants: number;
|
|
422
|
+
prices: {
|
|
423
|
+
variant: string;
|
|
424
|
+
from: number;
|
|
425
|
+
to: number;
|
|
426
|
+
}[];
|
|
427
|
+
}[];
|
|
428
|
+
unchanged: number;
|
|
429
|
+
only_in_destination: {
|
|
430
|
+
id: string;
|
|
431
|
+
name: string;
|
|
432
|
+
}[];
|
|
433
|
+
};
|
|
434
|
+
collections: {
|
|
435
|
+
create: string[];
|
|
436
|
+
update: string[];
|
|
437
|
+
};
|
|
438
|
+
discounts: {
|
|
439
|
+
create: string[];
|
|
440
|
+
update: string[];
|
|
441
|
+
};
|
|
442
|
+
settings: string[];
|
|
443
|
+
}
|
|
444
|
+
export type EmailTemplate = "order_confirmation" | "order_shipped" | "order_refunded" | "return_approved" | "checkout_recovery";
|
|
445
|
+
declare class Events extends Resource {
|
|
446
|
+
/** Poll events in order. Pass the last id you processed as `after`. `type` accepts wildcards like `order.*`. */
|
|
447
|
+
list(params?: {
|
|
448
|
+
after?: string;
|
|
449
|
+
type?: EventType | `${string}.*`;
|
|
450
|
+
limit?: number;
|
|
451
|
+
}): Promise<Result<List<Event<unknown>>>>;
|
|
452
|
+
}
|
|
453
|
+
export interface ChatgptChannel {
|
|
454
|
+
object: "chatgpt_channel";
|
|
455
|
+
status: "not_applied" | "applied" | "approved" | "not_approved";
|
|
456
|
+
applied_at: string | null;
|
|
457
|
+
decided_at: string | null;
|
|
458
|
+
ready_to_apply: boolean;
|
|
459
|
+
steps: {
|
|
460
|
+
key: string;
|
|
461
|
+
status: "done" | "todo" | "warning";
|
|
462
|
+
message: string;
|
|
463
|
+
fix?: string;
|
|
464
|
+
}[];
|
|
465
|
+
feed: Pick<FeedCheck, "items" | "items_ok" | "errors" | "warnings" | "formats">;
|
|
466
|
+
application: {
|
|
467
|
+
url: string;
|
|
468
|
+
answers: Record<string, string | boolean | null>;
|
|
469
|
+
you_provide: string[];
|
|
470
|
+
};
|
|
471
|
+
categories: string[];
|
|
472
|
+
next: string;
|
|
473
|
+
}
|
|
474
|
+
export interface FeedCheck {
|
|
475
|
+
object: "feed_check";
|
|
476
|
+
target: "openai";
|
|
477
|
+
items: number;
|
|
478
|
+
items_ok: number;
|
|
479
|
+
ready: boolean;
|
|
480
|
+
errors: {
|
|
481
|
+
item_id: string | null;
|
|
482
|
+
field: string;
|
|
483
|
+
message: string;
|
|
484
|
+
}[];
|
|
485
|
+
warnings: {
|
|
486
|
+
item_id: string | null;
|
|
487
|
+
field: string;
|
|
488
|
+
message: string;
|
|
489
|
+
}[];
|
|
490
|
+
formats: {
|
|
491
|
+
json: string;
|
|
492
|
+
jsonl_gz: string;
|
|
493
|
+
};
|
|
494
|
+
delivery: string;
|
|
495
|
+
}
|
|
496
|
+
export interface SetupItem {
|
|
497
|
+
key: string;
|
|
498
|
+
status: "done" | "todo" | "warning" | "optional";
|
|
499
|
+
message: string;
|
|
500
|
+
fix?: string;
|
|
501
|
+
}
|
|
502
|
+
export interface SetupStatus {
|
|
503
|
+
object: "setup_status";
|
|
504
|
+
store_id: string;
|
|
505
|
+
mode: "test" | "live";
|
|
506
|
+
ready_for_real_orders: boolean;
|
|
507
|
+
ready_for_test_orders: boolean;
|
|
508
|
+
next_step: SetupItem | null;
|
|
509
|
+
items: SetupItem[];
|
|
510
|
+
tip?: string;
|
|
511
|
+
}
|
|
512
|
+
export interface SimulatedOrder {
|
|
513
|
+
object: "simulated_order";
|
|
514
|
+
order: Order;
|
|
515
|
+
checkout_id: string;
|
|
516
|
+
events: string[];
|
|
517
|
+
webhooks: {
|
|
518
|
+
url: string;
|
|
519
|
+
deliveries: number;
|
|
520
|
+
}[];
|
|
521
|
+
emails_that_would_send: {
|
|
522
|
+
event: string;
|
|
523
|
+
to: string | null;
|
|
524
|
+
subject: string;
|
|
525
|
+
}[];
|
|
526
|
+
notes: string[];
|
|
527
|
+
}
|
|
528
|
+
export interface CatalogImport {
|
|
529
|
+
status: "running" | "succeeded" | "failed";
|
|
530
|
+
started_at: string;
|
|
531
|
+
finished_at?: string;
|
|
532
|
+
products_created: number;
|
|
533
|
+
products_updated: number;
|
|
534
|
+
variants_created: number;
|
|
535
|
+
variants_updated: number;
|
|
536
|
+
error?: string;
|
|
537
|
+
}
|
|
538
|
+
export interface GoLiveLink {
|
|
539
|
+
object: "go_live_link";
|
|
540
|
+
url: string;
|
|
541
|
+
expires_at: string;
|
|
542
|
+
steps: string[];
|
|
543
|
+
}
|
|
544
|
+
declare class StoreResource extends Resource {
|
|
545
|
+
get(): Promise<Result<Store>>;
|
|
546
|
+
/**
|
|
547
|
+
* Note on `tax_enabled`: Stripe only collects tax in jurisdictions where you have an active
|
|
548
|
+
* tax registration in Stripe Tax. Turning this on without registrations collects $0 tax.
|
|
549
|
+
*/
|
|
550
|
+
/**
|
|
551
|
+
* Preview a sync from this store's other version (test or live) into this store. Nothing changes.
|
|
552
|
+
* Syncs cover products, prices, images, collections, discounts and shipping/email settings; never orders, keys, Stripe, site URLs or stock counts.
|
|
553
|
+
*/
|
|
554
|
+
syncPreview(): Promise<Result<StoreSyncPlan>>;
|
|
555
|
+
/** Apply a sync into this store. Into a live store, pass the `plan_id` from syncPreview(). */
|
|
556
|
+
sync(params?: {
|
|
557
|
+
plan_id?: string;
|
|
558
|
+
}): Promise<Result<{
|
|
559
|
+
object: "sync_result";
|
|
560
|
+
products_created: number;
|
|
561
|
+
products_updated: number;
|
|
562
|
+
collections: number;
|
|
563
|
+
discounts: number;
|
|
564
|
+
settings: string[];
|
|
565
|
+
discount_errors: {
|
|
566
|
+
code: string;
|
|
567
|
+
message: string;
|
|
568
|
+
}[];
|
|
569
|
+
}>>;
|
|
570
|
+
update(params: {
|
|
571
|
+
name?: string;
|
|
572
|
+
tax_enabled?: boolean;
|
|
573
|
+
default_success_url?: string | null;
|
|
574
|
+
default_cancel_url?: string | null;
|
|
575
|
+
builtin_emails?: boolean;
|
|
576
|
+
recovery_emails?: boolean;
|
|
577
|
+
hosted_pages?: boolean;
|
|
578
|
+
/** Customer email branding. Logo is an https image URL; accent is a hex color like "#2f6f4e". */
|
|
579
|
+
email_brand?: {
|
|
580
|
+
logo_url?: string | null;
|
|
581
|
+
accent_color?: string | null;
|
|
582
|
+
address?: string | null;
|
|
583
|
+
};
|
|
584
|
+
/** Emails to your team: each new order, and when a variant's stock falls to the threshold (null turns it off). */
|
|
585
|
+
owner_alerts?: {
|
|
586
|
+
new_order?: boolean;
|
|
587
|
+
low_stock_threshold?: number | null;
|
|
588
|
+
};
|
|
589
|
+
}): Promise<Result<Store>>;
|
|
590
|
+
/**
|
|
591
|
+
* Would OpenAI's ChatGPT shopping accept this store's product feed? Per-item errors (rejected) and
|
|
592
|
+
* warnings (weaker listings), plus where the feed lives (JSON and the jsonl.gz upload format).
|
|
593
|
+
*/
|
|
594
|
+
checkFeed(): Promise<Result<FeedCheck>>;
|
|
595
|
+
/** Sell in ChatGPT: readiness steps, suggested answers for OpenAI's merchant application, and status. */
|
|
596
|
+
chatgpt(): Promise<Result<ChatgptChannel>>;
|
|
597
|
+
/** Record the application's progress (after the owner submits it) or the product category to apply with. */
|
|
598
|
+
updateChatgpt(params: {
|
|
599
|
+
status?: ChatgptChannel["status"];
|
|
600
|
+
category?: string | null;
|
|
601
|
+
note?: string;
|
|
602
|
+
}): Promise<Result<ChatgptChannel>>;
|
|
603
|
+
/** Everything between this store and real orders, each with the exact fix. Start here when setting up. */
|
|
604
|
+
setupStatus(): Promise<Result<SetupStatus>>;
|
|
605
|
+
/**
|
|
606
|
+
* Test stores only: run a purchase end to end without a browser. Stock is reserved and committed, the
|
|
607
|
+
* order is created and paid, events and your webhooks fire; `fulfill: true` also marks it shipped.
|
|
608
|
+
* Never charges a card, reaches Printify/Printful, emails anyone, or counts toward usage.
|
|
609
|
+
*/
|
|
610
|
+
simulateOrder(params: {
|
|
611
|
+
items: {
|
|
612
|
+
variant_id: string;
|
|
613
|
+
quantity: number;
|
|
614
|
+
properties?: Record<string, string>;
|
|
615
|
+
}[];
|
|
616
|
+
customer_email?: string;
|
|
617
|
+
customer_name?: string;
|
|
618
|
+
shipping_address?: {
|
|
619
|
+
line1: string;
|
|
620
|
+
line2?: string;
|
|
621
|
+
city: string;
|
|
622
|
+
state?: string;
|
|
623
|
+
postal_code: string;
|
|
624
|
+
country: string;
|
|
625
|
+
};
|
|
626
|
+
discount_code?: string;
|
|
627
|
+
shipping_rate?: {
|
|
628
|
+
name: string;
|
|
629
|
+
amount: number;
|
|
630
|
+
};
|
|
631
|
+
fulfill?: boolean;
|
|
632
|
+
metadata?: Record<string, string>;
|
|
633
|
+
}): Promise<Result<SimulatedOrder>>;
|
|
634
|
+
/**
|
|
635
|
+
* A one-time link (valid 7 days) to hand to a person when the store is ready for real orders. Opening it
|
|
636
|
+
* signs them in, claims the store if it's an unclaimed sandbox, creates a live copy (products, prices,
|
|
637
|
+
* inventory, settings and connections), and takes them to Connect Stripe. Test stores only.
|
|
638
|
+
*/
|
|
639
|
+
goLiveLink(): Promise<Result<GoLiveLink>>;
|
|
640
|
+
/**
|
|
641
|
+
* Shipping every checkout offers unless it passes its own rates: up to 5 flat rates (cents), the
|
|
642
|
+
* countries you ship to, and an optional free-shipping threshold on the item subtotal (cents).
|
|
643
|
+
*/
|
|
644
|
+
configureCheckoutShipping(params: {
|
|
645
|
+
countries: string[];
|
|
646
|
+
rates: {
|
|
647
|
+
name: string;
|
|
648
|
+
amount: number;
|
|
649
|
+
min_days?: number;
|
|
650
|
+
max_days?: number;
|
|
651
|
+
}[];
|
|
652
|
+
free_over?: number | null;
|
|
653
|
+
}): Promise<Result<Store>>;
|
|
654
|
+
/** Connect your EasyPost or Shippo account for label purchasing. */
|
|
655
|
+
configureShipping(params: {
|
|
656
|
+
provider: "easypost" | "shippo";
|
|
657
|
+
api_key: string;
|
|
658
|
+
ship_from: ShipFromAddress;
|
|
659
|
+
default_parcel?: Dimensions;
|
|
660
|
+
}): Promise<Result<Store>>;
|
|
661
|
+
/**
|
|
662
|
+
* Connect Printful or Printify (call once per provider; both can be connected — each variant routes to the
|
|
663
|
+
* provider it's mapped to). Paid orders with mapped variants are sent automatically — held for your
|
|
664
|
+
* approval in the provider's dashboard unless `auto_confirm: true`. Shipments mark orders fulfilled.
|
|
665
|
+
*/
|
|
666
|
+
configureFulfillment(params: {
|
|
667
|
+
provider: "printful";
|
|
668
|
+
api_key: string;
|
|
669
|
+
printful_store_id?: string;
|
|
670
|
+
auto_confirm?: boolean;
|
|
671
|
+
import_catalog?: boolean;
|
|
672
|
+
} | {
|
|
673
|
+
provider: "printify";
|
|
674
|
+
api_key: string;
|
|
675
|
+
printify_shop_id: string;
|
|
676
|
+
auto_confirm?: boolean;
|
|
677
|
+
import_catalog?: boolean;
|
|
678
|
+
}): Promise<Result<Store & {
|
|
679
|
+
fulfillment_webhook: {
|
|
680
|
+
url: string | null;
|
|
681
|
+
registered: boolean;
|
|
682
|
+
error?: string;
|
|
683
|
+
};
|
|
684
|
+
}>>;
|
|
685
|
+
/**
|
|
686
|
+
* Import products from Shopify: pass Shopify's product export CSV (Products → Export) as `csv`, or
|
|
687
|
+
* `shop` (your-store.myshopify.com) + a custom app `access_token` (read_products, read_inventory).
|
|
688
|
+
* Safe to re-run: products match by Shopify id or SKU and existing prices and stock are kept.
|
|
689
|
+
*/
|
|
690
|
+
importFromShopify(params: {
|
|
691
|
+
csv: string;
|
|
692
|
+
} | {
|
|
693
|
+
shop: string;
|
|
694
|
+
access_token: string;
|
|
695
|
+
}): Promise<Result<CatalogImport & {
|
|
696
|
+
object: "import";
|
|
697
|
+
source: "shopify";
|
|
698
|
+
products_seen: number;
|
|
699
|
+
warnings: string[];
|
|
700
|
+
}>>;
|
|
701
|
+
/**
|
|
702
|
+
* Import the products already set up in a connected Printify shop or Printful store (both when omitted).
|
|
703
|
+
* Runs in the background and happens automatically on connect; safe to re-run. Progress: `store.get()` → fulfillment[].catalog_import.
|
|
704
|
+
*/
|
|
705
|
+
importCatalog(params?: {
|
|
706
|
+
provider?: "printful" | "printify";
|
|
707
|
+
}): Promise<Result<{
|
|
708
|
+
object: "list";
|
|
709
|
+
data: ({
|
|
710
|
+
provider: "printful" | "printify";
|
|
711
|
+
} & CatalogImport)[];
|
|
712
|
+
}>>;
|
|
713
|
+
/** Disconnect one provider, or all when omitted. */
|
|
714
|
+
disableFulfillment(provider?: "printful" | "printify"): Promise<Result<Store>>;
|
|
715
|
+
/** Send customer emails (confirmation, shipped, refunded, return approved) from your domain via Resend. */
|
|
716
|
+
configureEmails(params: {
|
|
717
|
+
resend_api_key: string;
|
|
718
|
+
from: string;
|
|
719
|
+
reply_to?: string;
|
|
720
|
+
events?: ("order.paid" | "order.fulfilled" | "order.refunded" | "return.approved")[];
|
|
721
|
+
}): Promise<Result<Store>>;
|
|
722
|
+
disableEmails(): Promise<Result<Store>>;
|
|
723
|
+
/**
|
|
724
|
+
* Publish product feeds for AI shopping surfaces (OpenAI/ACP JSON, Google Merchant XML) and,
|
|
725
|
+
* with `agent_access: true`, a public API third-party shopping agents can use to create checkout links.
|
|
726
|
+
*/
|
|
727
|
+
configureStorefront(params: StorefrontConfig & {
|
|
728
|
+
agent_access?: boolean;
|
|
729
|
+
}): Promise<Result<Store>>;
|
|
730
|
+
}
|
|
731
|
+
declare class Webhooks extends Resource {
|
|
732
|
+
create(params: {
|
|
733
|
+
url: string;
|
|
734
|
+
events?: (EventType | "*" | `${string}.*`)[];
|
|
735
|
+
}): Promise<Result<WebhookEndpoint>>;
|
|
736
|
+
list(): Promise<Result<List<WebhookEndpoint>>>;
|
|
737
|
+
remove(id: string): Promise<Result<{
|
|
738
|
+
id: string;
|
|
739
|
+
deleted: true;
|
|
740
|
+
}>>;
|
|
741
|
+
/** Verify a webhook we sent you. Throws if the signature is invalid or too old. */
|
|
742
|
+
verify(args: {
|
|
743
|
+
payload: string;
|
|
744
|
+
headers: Headers | Record<string, string | undefined>;
|
|
745
|
+
secret: string;
|
|
746
|
+
toleranceSeconds?: number;
|
|
747
|
+
}): Promise<Event<unknown>>;
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* Verify a CommerceForAI webhook (Standard Webhooks format). Works in Node 18+, Bun, Deno and edge runtimes.
|
|
751
|
+
* Pass the raw request body string, not parsed JSON.
|
|
752
|
+
*/
|
|
753
|
+
export declare function verifyWebhook({ payload, headers, secret, toleranceSeconds, }: {
|
|
754
|
+
payload: string;
|
|
755
|
+
headers: Headers | Record<string, string | undefined>;
|
|
756
|
+
secret: string;
|
|
757
|
+
toleranceSeconds?: number;
|
|
758
|
+
}): Promise<Event>;
|
|
759
|
+
export default Commerce;
|
|
760
|
+
export { createCheckoutHandler, type CheckoutHandlerOptions } from "./checkout-handler.js";
|
|
761
|
+
export * from "./cart-core.js";
|