Improve webhook client api and make script to register webhooks
This commit is contained in:
@@ -55,7 +55,7 @@ class ProductsClient {
|
||||
method: "GET",
|
||||
headers: this.creds.authHeaders,
|
||||
});
|
||||
if (!res.ok) throw new PrintfulError("Failed to get all Printful products", res.status, await parsePayload(res));
|
||||
if (!res.ok) throw new PrintfulError("Failed to list Printful products", res.status, await parsePayload(res));
|
||||
const payload = (await res.json()) as Printful.MetaDataMulti<Printful.Products.SyncProduct>;
|
||||
allSyncProducts.push(...payload.result);
|
||||
offset = allSyncProducts.length;
|
||||
@@ -111,7 +111,7 @@ class OrdersClient {
|
||||
method: "GET",
|
||||
headers: this.creds.authHeaders,
|
||||
});
|
||||
if (!res.ok) throw new PrintfulError("Failed to get all Printful orders", res.status, await parsePayload(res));
|
||||
if (!res.ok) throw new PrintfulError("Failed to list Printful orders", res.status, await parsePayload(res));
|
||||
const payload = (await res.json()) as Printful.MetaDataMulti<Printful.Orders.Order>;
|
||||
allPrintfulOrders.push(...payload.result);
|
||||
offset = allPrintfulOrders.length;
|
||||
@@ -124,7 +124,7 @@ class OrdersClient {
|
||||
class WebhooksClient {
|
||||
constructor(private creds: Credentials) { }
|
||||
|
||||
async getConfig(): Promise<Printful.Webhook.Config | undefined> {
|
||||
async get(): Promise<Printful.Webhook.Config | undefined> {
|
||||
const res = await fetch(`${this.creds.apiUrl}/webhooks`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
@@ -138,7 +138,11 @@ class WebhooksClient {
|
||||
return payload;
|
||||
}
|
||||
|
||||
async register(url: string, events: Printful.Webhook.Event[]) {
|
||||
|
||||
/**
|
||||
* Printful only supports one URL at a time, so subsequent calls will overwrite the previous webhook
|
||||
*/
|
||||
async create(url: string, events: Printful.Webhook.Event[]) {
|
||||
const res = await fetch(`${this.creds.apiUrl}/webhooks`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
|
||||
@@ -197,7 +197,7 @@ export namespace Webflow {
|
||||
export type MetaDataMulti<K extends string, T = any> = {
|
||||
[P in K]: T[];
|
||||
} & {
|
||||
pagination: {
|
||||
pagination?: {
|
||||
limit: number;
|
||||
offset: number;
|
||||
total: number;
|
||||
@@ -442,6 +442,16 @@ export namespace Webflow {
|
||||
OrderUpdated = "ecomm_order_changed",
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
id: string,
|
||||
triggerType: Event,
|
||||
url: string,
|
||||
workspaceId: string,
|
||||
siteId: string,
|
||||
lastTriggered: string,
|
||||
createdOn: string
|
||||
}
|
||||
|
||||
export interface OrderCreated extends MetaData<
|
||||
Event.OrderCreated,
|
||||
Orders.Order
|
||||
|
||||
@@ -13,6 +13,7 @@ type ClientOptions = {
|
||||
};
|
||||
|
||||
type Credentials = {
|
||||
apiBaseUrl: string;
|
||||
apiSitesUrl: string;
|
||||
apiCollectionsUrl: string;
|
||||
authHeader: Record<string, string>;
|
||||
@@ -103,11 +104,11 @@ class ProductsClient {
|
||||
method: "GET",
|
||||
headers: this.creds.authHeader,
|
||||
});
|
||||
if (!res.ok) throw new WebflowError("Failed to get all Webflow products", res.status, await parsePayload(res));
|
||||
if (!res.ok) throw new WebflowError("Failed to list Webflow products", res.status, await parsePayload(res));
|
||||
const payload = (await res.json()) as Webflow.MetaDataMulti<"items", Webflow.Products.ProductAndSkus>;
|
||||
allWebflowProducts.push(...payload.items);
|
||||
offset = allWebflowProducts.length;
|
||||
if (allWebflowProducts.length >= payload.pagination.total) break;
|
||||
if (allWebflowProducts.length >= (payload?.pagination?.total ?? 0)) break;
|
||||
} while (opt.forceAll);
|
||||
return allWebflowProducts;
|
||||
}
|
||||
@@ -168,11 +169,11 @@ class OrdersClient {
|
||||
method: "GET",
|
||||
headers: this.creds.authHeader,
|
||||
});
|
||||
if (!res.ok) throw new WebflowError("Failed to get all Webflow orders", res.status, await parsePayload(res));
|
||||
if (!res.ok) throw new WebflowError("Failed to list Webflow orders", res.status, await parsePayload(res));
|
||||
const payload = (await res.json()) as Webflow.MetaDataMulti<"orders", Webflow.Orders.Order>;
|
||||
allOrders.push(...payload.orders);
|
||||
offset = allOrders.length;
|
||||
if (allOrders.length >= payload.pagination.total) break;
|
||||
if (allOrders.length >= (payload?.pagination?.total ?? 0)) break;
|
||||
} while (opt.forceAll);
|
||||
return allOrders;
|
||||
}
|
||||
@@ -213,6 +214,60 @@ class OrdersClient {
|
||||
}
|
||||
}
|
||||
|
||||
class WebhooksClient {
|
||||
constructor(private creds: Credentials) { }
|
||||
|
||||
async list(opt: PagingOptions = {}): Promise<Webflow.Webhook.Config[]> {
|
||||
const allWebhooks: Webflow.Webhook.Config[] = [];
|
||||
let offset = opt.offset ?? 0;
|
||||
do {
|
||||
const res = await fetch(`${this.creds.apiSitesUrl}/webhooks?offset=${offset}&limit=${opt.limit ?? 100}`, {
|
||||
method: "GET",
|
||||
headers: this.creds.authHeader,
|
||||
});
|
||||
if (!res.ok) throw new WebflowError("Failed to list Webflow webhooks", res.status, await parsePayload(res));
|
||||
const payload = (await res.json()) as Webflow.MetaDataMulti<"webhooks", Webflow.Webhook.Config>;
|
||||
allWebhooks.push(...payload.webhooks);
|
||||
offset = allWebhooks.length;
|
||||
if (allWebhooks.length >= (payload?.pagination?.total ?? 0)) break;
|
||||
} while (opt.forceAll);
|
||||
return allWebhooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit of 75 registrations per event
|
||||
*/
|
||||
async create(url: string, event: Webflow.Webhook.Event) {
|
||||
const res = await fetch(`${this.creds.apiSitesUrl}/webhooks`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...this.creds.authHeader,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"url": url,
|
||||
"triggerType": event
|
||||
}),
|
||||
});
|
||||
if (!res.ok) throw new WebflowError("Failed to create Webflow webhook", res.status, await parsePayload(res));
|
||||
}
|
||||
|
||||
async remove(webhookId: string): Promise<void> {
|
||||
const res = await fetch(
|
||||
`${this.creds.apiBaseUrl}/webhooks/${webhookId}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...this.creds.authHeader,
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
},
|
||||
);
|
||||
if (!res.ok) throw new WebflowError("Failed to remove Webflow webhook", res.status, await parsePayload(res));
|
||||
}
|
||||
}
|
||||
|
||||
class UtilClient {
|
||||
constructor(private webhookSecret: string) { }
|
||||
|
||||
@@ -248,16 +303,19 @@ class UtilClient {
|
||||
export class WebflowClient {
|
||||
readonly Products: ProductsClient;
|
||||
readonly Orders: OrdersClient;
|
||||
readonly Webhooks: WebhooksClient;
|
||||
readonly Util: UtilClient;
|
||||
|
||||
constructor(options: ClientOptions) {
|
||||
const creds: Credentials = {
|
||||
apiBaseUrl: `https://api.webflow.com/v2`,
|
||||
apiSitesUrl: `https://api.webflow.com/v2/sites/${options.siteId}`,
|
||||
apiCollectionsUrl: `https://api.webflow.com/v2/collections/${options.collectionsId}`,
|
||||
authHeader: { Authorization: `bearer ${options.token}` },
|
||||
};
|
||||
this.Products = new ProductsClient(creds);
|
||||
this.Orders = new OrdersClient(creds);
|
||||
this.Webhooks = new WebhooksClient(creds);
|
||||
this.Util = new UtilClient(options.webhookSecret);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user