Skip to content

Commit b800212

Browse files
committed
Fold functions-pickup-point-delivery-option-generators js and ts impl
1 parent 71e1b03 commit b800212

File tree

18 files changed

+413
-5888
lines changed

18 files changed

+413
-5888
lines changed

functions-pickup-point-delivery-option-generators-js/src/fetch.liquid

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{%- if flavor contains "vanilla-js" -%}
12
export function fetch(input) {
23
let { countryCode, longitude, latitude } = input.deliveryAddress;
34
if (longitude && latitude && countryCode === 'CA') {
@@ -25,3 +26,43 @@ function buildExternalApiRequest(latitude, longitude) {
2526
},
2627
};
2728
}
29+
{%- elsif flavor contains "typescript" -%}
30+
import {
31+
Maybe,
32+
Allocation,
33+
MailingAddress,
34+
CountryCode,
35+
HttpRequest,
36+
HttpRequestMethod,
37+
FunctionFetchResult,
38+
FetchInput
39+
} from '../generated/api';
40+
41+
export function fetch(input: FetchInput): FunctionFetchResult {
42+
let { countryCode, longitude, latitude } = input.deliveryAddress;
43+
if (longitude && latitude && countryCode === CountryCode.Ca) {
44+
return {
45+
request: buildExternalApiRequest(latitude, longitude),
46+
};
47+
}
48+
return { request: null };
49+
}
50+
51+
function buildExternalApiRequest(latitude: number, longitude: number): HttpRequest {
52+
// The latitude and longitude parameters are included in the URL for demonstration purposes only. They do not influence the result.
53+
let url = `https://cdn.shopify.com/s/files/1/0628/3830/9033/files/pickup-points-external-api-v2.json?v=1714588690&lat=${latitude}&lon=${longitude}`;
54+
55+
return {
56+
method: HttpRequestMethod.Get,
57+
url,
58+
headers: [{
59+
name: "Accept",
60+
value: "application/json; charset=utf-8"
61+
}],
62+
body: null,
63+
policy: {
64+
readTimeoutMs: 500,
65+
},
66+
};
67+
}
68+
{%- endif -%}

functions-pickup-point-delivery-option-generators-js/src/fetch.test.liquid

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{%- if flavor contains "vanilla-js" -%}
12
import { describe, it, expect } from 'vitest';
23
import { fetch } from './fetch';
34

@@ -44,3 +45,49 @@ describe('fetch function', () => {
4445
expect(result).toEqual(expected);
4546
});
4647
});
48+
{%- elsif flavor contains "typescript" -%}
49+
import { describe, it, expect } from 'vitest';
50+
import { fetch } from './fetch';
51+
52+
import { CountryCode, FunctionFetchResult, HttpRequestMethod } from '../generated/api';
53+
54+
describe('fetch function', () => {
55+
it('returns a request when country is Canada', () => {
56+
const result = fetch({
57+
deliveryAddress: {
58+
countryCode: CountryCode.Ca,
59+
longitude: 12.3,
60+
latitude: 45.6,
61+
}
62+
});
63+
const expected: FunctionFetchResult = ({
64+
request: {
65+
body: null,
66+
headers: [
67+
{ name: "Accept", value: "application/json; charset=utf-8" },
68+
],
69+
method: HttpRequestMethod.Get,
70+
policy: {
71+
readTimeoutMs: 500,
72+
},
73+
url: 'https://cdn.shopify.com/s/files/1/0628/3830/9033/files/pickup-points-external-api-v2.json?v=1714588690&lat=45.6&lon=12.3',
74+
}
75+
});
76+
77+
expect(result).toEqual(expected);
78+
});
79+
80+
it('returns no request when country is not Canada', () => {
81+
const result = fetch({
82+
deliveryAddress: {
83+
countryCode: CountryCode.Us,
84+
longitude: 12.3,
85+
latitude: 45.6,
86+
}
87+
});
88+
const expected: FunctionFetchResult = ({ request: null });
89+
90+
expect(result).toEqual(expected);
91+
});
92+
});
93+
{%- endif -%}

functions-pickup-point-delivery-option-generators-js/src/run.liquid

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{%- if flavor contains "vanilla-js" -%}
12
export function run(input) {
23
const { fetchResult } = input;
34
const status = fetchResult?.status;
@@ -101,3 +102,118 @@ function formatTime(time) {
101102

102103
return `${hourIn24Format.toString().padStart(2, '0')}:${min}:00`;
103104
}
105+
{%- elsif flavor contains "typescript" -%}
106+
import {
107+
BusinessHours,
108+
FunctionRunResult,
109+
Operation,
110+
PickupAddress,
111+
PickupPointDeliveryOption,
112+
Provider,
113+
RunInput
114+
} from "../generated/api";
115+
116+
export function run(input: RunInput): FunctionRunResult {
117+
const { fetchResult } = input;
118+
const status = fetchResult?.status;
119+
const body = fetchResult?.body;
120+
121+
let operations: Operation[] = [];
122+
123+
if (status === 200 && body) {
124+
const { deliveryPoints: externalApiDeliveryPoints } = JSON.parse(body);
125+
operations = buildPickupPointDeliveryOptionOperations(externalApiDeliveryPoints);
126+
}
127+
128+
return { operations };
129+
130+
}
131+
132+
function buildPickupPointDeliveryOptionOperations(externalApiDeliveryPoints: any[]): Operation[] {
133+
return externalApiDeliveryPoints
134+
.map(externalApiDeliveryPoint => ({ add: buildPickupPointDeliveryOption(externalApiDeliveryPoint) }));
135+
}
136+
137+
function buildPickupPointDeliveryOption(externalApiDeliveryPoint: any): PickupPointDeliveryOption {
138+
return {
139+
cost: null,
140+
pickupPoint: {
141+
externalId: externalApiDeliveryPoint.pointId,
142+
name: externalApiDeliveryPoint.pointName,
143+
provider: buildProvider(),
144+
address: buildAddress(externalApiDeliveryPoint),
145+
businessHours: buildBusinessHours(externalApiDeliveryPoint),
146+
},
147+
};
148+
}
149+
150+
function buildProvider(): Provider {
151+
return {
152+
name: "Shopify TypeScript Demo",
153+
logoUrl: "https://cdn.shopify.com/s/files/1/0628/3830/9033/files/shopify_icon_146101.png?v=1706120545",
154+
};
155+
}
156+
157+
function buildAddress(externalApiDeliveryPoint: any): PickupAddress {
158+
let location = externalApiDeliveryPoint.location;
159+
let addressComponents = location.addressComponents;
160+
let geometry = location.geometry.location;
161+
let administrativeArea = addressComponents.administrativeArea;
162+
163+
return {
164+
address1: `${addressComponents.streetNumber} ${addressComponents.route}`,
165+
address2: null,
166+
city: addressComponents.locality,
167+
country: addressComponents.country,
168+
countryCode: addressComponents.countryCode,
169+
latitude: geometry.lat,
170+
longitude: geometry.lng,
171+
phone: null,
172+
province: administrativeArea.name,
173+
provinceCode: administrativeArea.code,
174+
zip: addressComponents.postalCode,
175+
};
176+
}
177+
178+
// Transforms the opening hours of a delivery point into a vector of `BusinessHours` objects.
179+
// Each day's opening hours are represented using a `BusinessHours` object as follows:
180+
// "Monday: 9:00 AM – 5:00 PM" is transformed to {day: "MONDAY", periods: [{opening_time: "09:00:00", closing_time: "17:00:00"}]}
181+
// "Tuesday: Closed" is transformed to {day: "TUESDAY", periods: []}
182+
function buildBusinessHours(externalApiDeliveryPoint: any): BusinessHours[] | null {
183+
if(!externalApiDeliveryPoint.openingHours){
184+
return null;
185+
}
186+
187+
return externalApiDeliveryPoint.openingHours.weekdayText
188+
.map((dayOpeningHours: string) => {
189+
let dayOpeningHoursParts = dayOpeningHours.split(": ");
190+
let dayName = dayOpeningHoursParts[0].toUpperCase();
191+
if (dayOpeningHoursParts[1] === "Closed") {
192+
return { day: dayName, periods: [] };
193+
} else {
194+
let openingClosingTimes = dayOpeningHoursParts[1].split(" – ");
195+
return {
196+
day: dayName,
197+
periods: [{
198+
openingTime: formatTime(openingClosingTimes[0]),
199+
closingTime: formatTime(openingClosingTimes[1]),
200+
}],
201+
};
202+
}
203+
});
204+
}
205+
206+
// Converts a time string from 12-hour to 24-hour format.
207+
// Example: "9:00 AM" => "09:00:00", "5:00 PM" => "17:00:00"
208+
function formatTime(time: string): string {
209+
let timeParts = time.split(' ');
210+
let hourMin = timeParts[0].split(':');
211+
let hour = parseInt(hourMin[0]);
212+
let min = hourMin[1];
213+
let period = timeParts[1];
214+
215+
let hourIn24Format = period === 'AM' ? (hour === 12 ? 0 : hour) : (hour === 12 ? hour : hour + 12);
216+
217+
return `${hourIn24Format.toString().padStart(2, '0')}:${min}:00`;
218+
}
219+
{%- endif -%}

0 commit comments

Comments
 (0)