Skip to content

Commit ed71f9b

Browse files
authored
New Components - easyship (#16818)
* new components * pnpm-lock.yaml * updates * updates
1 parent 17c06e8 commit ed71f9b

File tree

14 files changed

+540
-20
lines changed

14 files changed

+540
-20
lines changed

components/easyship/.gitignore

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
import easyship from "../../easyship.app.mjs";
2+
3+
export default {
4+
key: "easyship-create-shipment",
5+
name: "Create Shipment",
6+
description: "Create a new shipment in Easyship. [See the docs](https://developers.easyship.com/reference/shipments_create)",
7+
version: "0.0.1",
8+
type: "action",
9+
props: {
10+
easyship,
11+
originContactName: {
12+
type: "string",
13+
label: "Origin Name",
14+
description: "The full name of a person at the origin address",
15+
},
16+
originContactEmail: {
17+
type: "string",
18+
label: "Origin Email",
19+
description: "Email address used to reach the person in `Origin Name`",
20+
},
21+
originContactPhone: {
22+
type: "string",
23+
label: "Origin Phone Number",
24+
description: "Phone number used to reach the person in `Origin Name` (may or may not be SMS-ready)",
25+
},
26+
originCompanyName: {
27+
type: "string",
28+
label: "Origin Company Name",
29+
description: "The company or organization at the originaddress",
30+
},
31+
originLine1: {
32+
type: "string",
33+
label: "Origin Street Address",
34+
description: "Street address of the origin address",
35+
},
36+
originCity: {
37+
type: "string",
38+
label: "Origin City",
39+
description: "City of the origin address",
40+
},
41+
originState: {
42+
type: "string",
43+
label: "Origin State",
44+
description: "State, Province, or other top-level administrative region of the origin address",
45+
},
46+
originPostalCode: {
47+
type: "string",
48+
label: "Origin Postal Code",
49+
description: "Postal code of the origin address",
50+
},
51+
originCountry: {
52+
type: "string",
53+
label: "Origin Country (Alpha-2 Code)",
54+
description: "ISO 3166-1 alpha-2 code of the origin country",
55+
optional: true,
56+
},
57+
destinationName: {
58+
type: "string",
59+
label: "Destination Name",
60+
description: "The full name of a person at the destination address.",
61+
},
62+
destinationEmail: {
63+
type: "string",
64+
label: "Destination Email",
65+
description: "Email address used to reach the person at the destination address.",
66+
},
67+
destinationPhoneNumber: {
68+
type: "string",
69+
label: "Destination Phone Number",
70+
description: "Phone number used to reach the person at the destination address (may or may not be SMS-ready).",
71+
},
72+
destinationCompanyName: {
73+
type: "string",
74+
label: "Destination Company Name",
75+
description: "The company or organization at the destination address.",
76+
optional: true,
77+
},
78+
destinationStreetAddress: {
79+
type: "string",
80+
label: "Destination Street Address",
81+
description: "Street address of the destination address.",
82+
},
83+
destinationCity: {
84+
type: "string",
85+
label: "Destination City",
86+
description: "City of the destination address.",
87+
},
88+
destinationState: {
89+
type: "string",
90+
label: "Destination State",
91+
description: "State, Province, or other top-level administrative region of the destination address.",
92+
},
93+
destinationPostalCode: {
94+
type: "string",
95+
label: "Destination Postal Code",
96+
description: "Postal code of the destination address.",
97+
},
98+
destinationCountry: {
99+
type: "string",
100+
label: "Destination Country (Alpha-2 Code)",
101+
description: "ISO 3166-1 alpha-2 code of the destination country.",
102+
},
103+
numberOfParcels: {
104+
type: "integer",
105+
label: "Number of Parcels",
106+
description: "The number of parcels to ship",
107+
reloadProps: true,
108+
},
109+
},
110+
async additionalProps() {
111+
const props = {};
112+
if (this.numberOfParcels > 0) {
113+
for (let i = 1; i <= this.numberOfParcels; i++) {
114+
props[`parcelWeight${i}`] = {
115+
type: "string",
116+
label: `Parcel ${i} Weight (kg)`,
117+
description: `Item actual weight in kg of parcel ${i}`,
118+
};
119+
props[`parcelLength${i}`] = {
120+
type: "string",
121+
label: `Parcel ${i} Length (cm)`,
122+
description: `Length of parcel ${i}`,
123+
};
124+
props[`parcelWidth${i}`] = {
125+
type: "string",
126+
label: `Parcel ${i} Width (cm)`,
127+
description: `Width of parcel ${i}`,
128+
};
129+
props[`parcelHeight${i}`] = {
130+
type: "string",
131+
label: `Parcel ${i} Height (cm)`,
132+
description: `Height of parcel ${i}`,
133+
};
134+
props[`parcelDescription${i}`] = {
135+
type: "string",
136+
label: `Parcel ${i} Description`,
137+
description: `Description of parcel ${i}`,
138+
};
139+
props[`parcelValue${i}`] = {
140+
type: "string",
141+
label: `Parcel ${i} Value`,
142+
description: `Value of parcel ${i}`,
143+
};
144+
props[`parcelCurrency${i}`] = {
145+
type: "string",
146+
label: `Parcel ${i} Currency`,
147+
description: `Currency of parcel ${i} value`,
148+
};
149+
props[`parcelCategory${i}`] = {
150+
type: "string",
151+
label: `Parcel ${i} Category`,
152+
description: `Category of parcel ${i}`,
153+
options: await this.getCategoriesOptions(),
154+
};
155+
}
156+
}
157+
return props;
158+
},
159+
methods: {
160+
async getCategoriesOptions() {
161+
const categories = await this.easyship.getPaginatedResources({
162+
fn: this.easyship.listCategories,
163+
resourceKey: "item_categories",
164+
});
165+
return categories.map((c) => ({
166+
label: c.name,
167+
value: c.slug,
168+
}));
169+
},
170+
},
171+
async run({ $ }) {
172+
const parcelItems = [];
173+
for (let i = 1; i <= this.numberOfParcels; i++) {
174+
parcelItems.push({
175+
dimensions: {
176+
length: this[`parcelLength${i}`],
177+
width: this[`parcelWidth${i}`],
178+
height: this[`parcelHeight${i}`],
179+
},
180+
actual_weight: this[`parcelWeight${i}`],
181+
description: this[`parcelDescription${i}`],
182+
declared_customs_value: this[`parcelValue${i}`],
183+
declared_currency: this[`parcelCurrency${i}`] || "USD",
184+
category: this[`parcelCategory${i}`],
185+
});
186+
}
187+
const response = await this.easyship.createShipment({
188+
$,
189+
data: {
190+
origin_address: {
191+
contact_name: this.originContactName,
192+
contact_email: this.originContactEmail,
193+
contact_phone: this.originContactPhone,
194+
company_name: this.originCompanyName,
195+
line_1: this.originLine1,
196+
city: this.originCity,
197+
state: this.originState,
198+
postal_code: this.originPostalCode,
199+
country_alpha2: this.originCountry,
200+
},
201+
destination_address: {
202+
contact_name: this.destinationName,
203+
contact_email: this.destinationEmail,
204+
contact_phone: this.destinationPhoneNumber,
205+
company_name: this.destinationCompanyName,
206+
line_1: this.destinationStreetAddress,
207+
city: this.destinationCity,
208+
state: this.destinationState,
209+
postal_code: this.destinationPostalCode,
210+
country_alpha2: this.destinationCountry,
211+
},
212+
parcels: [
213+
{
214+
items: parcelItems,
215+
},
216+
],
217+
},
218+
});
219+
$.export("$summary", `Created shipment with ID: ${response.shipment.easyship_shipment_id}`);
220+
return response;
221+
},
222+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import easyship from "../../easyship.app.mjs";
2+
3+
export default {
4+
key: "easyship-find-shipment",
5+
name: "Find Shipment",
6+
description: "Find a shipment by ID. [See the documentation](https://developers.easyship.com/reference/shipments_index)",
7+
version: "0.0.1",
8+
type: "action",
9+
props: {
10+
easyship,
11+
shipmentId: {
12+
propDefinition: [
13+
easyship,
14+
"shipmentId",
15+
],
16+
},
17+
},
18+
async run({ $ }) {
19+
const response = await this.easyship.getShipment({
20+
$,
21+
shipmentId: this.shipmentId,
22+
});
23+
$.export("$summary", `Found shipment with ID: ${this.shipmentId}`);
24+
return response;
25+
},
26+
};

components/easyship/app/easyship.app.ts

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { axios } from "@pipedream/platform";
2+
3+
export default {
4+
type: "app",
5+
app: "easyship",
6+
propDefinitions: {
7+
shipmentId: {
8+
type: "string",
9+
label: "Shipment ID",
10+
description: "The ID of the shipment to find",
11+
async options({ page }) {
12+
const { shipments } = await this.listShipments({
13+
params: {
14+
page: page + 1,
15+
per_page: 100,
16+
},
17+
});
18+
return shipments.map((shipment) => shipment.easyship_shipment_id );
19+
},
20+
},
21+
},
22+
methods: {
23+
_baseUrl() {
24+
return "https://public-api.easyship.com/2024-09";
25+
},
26+
_makeRequest({
27+
$ = this, path, ...opts
28+
}) {
29+
return axios($, {
30+
url: `${this._baseUrl()}${path}`,
31+
headers: {
32+
Authorization: `Bearer ${this.$auth.api_token}`,
33+
Accept: "application/json",
34+
},
35+
...opts,
36+
});
37+
},
38+
createWebhook(opts = {}) {
39+
return this._makeRequest({
40+
path: "/webhooks",
41+
method: "POST",
42+
...opts,
43+
});
44+
},
45+
activateWebhook({
46+
webhookId, ...opts
47+
}) {
48+
return this._makeRequest({
49+
path: `/webhooks/${webhookId}/activate`,
50+
method: "POST",
51+
...opts,
52+
});
53+
},
54+
deleteWebhook({
55+
webhookId, ...opts
56+
}) {
57+
return this._makeRequest({
58+
path: `/webhooks/${webhookId}`,
59+
method: "DELETE",
60+
...opts,
61+
});
62+
},
63+
getShipment({
64+
shipmentId, ...opts
65+
}) {
66+
return this._makeRequest({
67+
path: `/shipments/${shipmentId}`,
68+
...opts,
69+
});
70+
},
71+
listCategories(opts = {}) {
72+
return this._makeRequest({
73+
path: "/item_categories",
74+
...opts,
75+
});
76+
},
77+
listShipments(opts = {}) {
78+
return this._makeRequest({
79+
path: "/shipments",
80+
...opts,
81+
});
82+
},
83+
createShipment(opts = {}) {
84+
return this._makeRequest({
85+
path: "/shipments",
86+
method: "POST",
87+
...opts,
88+
});
89+
},
90+
async *paginate({
91+
fn, params, resourceKey, max,
92+
}) {
93+
params = {
94+
...params,
95+
page: 1,
96+
per_page: 100,
97+
};
98+
let total, count = 0;
99+
do {
100+
const response = await fn({
101+
params,
102+
});
103+
const items = response[resourceKey];
104+
for (const item of items) {
105+
yield item;
106+
if (max && ++count >= max) {
107+
return;
108+
}
109+
}
110+
params.page++;
111+
total = items.length;
112+
} while (total === params.per_page);
113+
},
114+
async getPaginatedResources(opts = {}) {
115+
const results = [];
116+
for await (const item of this.paginate(opts)) {
117+
results.push(item);
118+
}
119+
return results;
120+
},
121+
},
122+
};

0 commit comments

Comments
 (0)