Skip to content

Commit 1062f32

Browse files
authored
Merge pull request #70 from Foxy/beta
chore: release 1.16.0
2 parents 4b186c3 + 5811e5c commit 1062f32

File tree

11 files changed

+159
-51
lines changed

11 files changed

+159
-51
lines changed

src/backend/API.ts

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -138,44 +138,73 @@ export class API extends Core.API<Graph> {
138138

139139
private async __fetch(input: RequestInfo, init?: RequestInit): Promise<Response> {
140140
let token = JSON.parse(this.storage.getItem(API.ACCESS_TOKEN) ?? 'null') as StoredToken | null;
141-
const request = new Request(input, init);
142-
143-
if (token !== null) {
144-
const expiresAt = new Date(token.date_created).getTime() + token.expires_in * 1000;
145-
const refreshAt = Date.now() + API.REFRESH_THRESHOLD;
146-
147-
if (expiresAt < refreshAt) {
148-
this.storage.removeItem(API.ACCESS_TOKEN);
149-
this.console.info('Removed old access token from the storage.');
150-
token = null;
151-
}
152-
}
153-
154-
if (token === null) {
155-
this.console.trace("Access token isn't present in the storage. Fetching a new one...");
141+
let request = new Request(input, init);
142+
let headers = request.headers;
156143

144+
const fetchNewAccessToken = async () => {
145+
this.console.trace('Fetching a new access token...');
157146
const rawToken = await API.getToken(this, true).catch(err => {
158147
this.console.error(err.message);
159148
return null;
160149
});
161150

162151
if (rawToken) {
163-
token = { ...rawToken, date_created: new Date().toISOString() };
152+
const token = { ...rawToken, date_created: new Date().toISOString() };
164153
this.storage.setItem(API.ACCESS_TOKEN, JSON.stringify(token));
165154
this.console.info('Access token updated.');
155+
return token;
166156
} else {
167157
this.console.warn('Failed to fetch access token. Proceeding without authentication.');
158+
return null;
168159
}
160+
};
161+
162+
const setHeaders = (accessToken?: string) => {
163+
if (!headers.get('Authorization') && accessToken) headers.set('Authorization', `Bearer ${accessToken}`);
164+
if (!headers.get('Content-Type')) headers.set('Content-Type', 'application/json');
165+
if (!headers.get('FOXY-API-VERSION')) headers.set('FOXY-API-VERSION', this.version);
166+
};
167+
168+
if (token) {
169+
const expiresAt = new Date(token.date_created).getTime() + token.expires_in * 1000;
170+
const refreshAt = Date.now() + API.REFRESH_THRESHOLD;
171+
172+
if (expiresAt < refreshAt) {
173+
this.storage.removeItem(API.ACCESS_TOKEN);
174+
this.console.info('Removed old access token from the storage.');
175+
token = await fetchNewAccessToken();
176+
}
177+
} else {
178+
this.console.trace("Access token isn't present in the storage.");
179+
token = await fetchNewAccessToken();
169180
}
170181

171-
const headers = request.headers;
182+
setHeaders(token?.access_token);
172183
const method = init?.method?.toUpperCase() ?? 'GET';
184+
this.console.trace(`${method} ${request.url}`);
185+
let response = await fetch(request);
173186

174-
if (!headers.get('Authorization') && token) headers.set('Authorization', `Bearer ${token.access_token}`);
175-
if (!headers.get('Content-Type')) headers.set('Content-Type', 'application/json');
176-
if (!headers.get('FOXY-API-VERSION')) headers.set('FOXY-API-VERSION', this.version);
187+
if (response.status === 401) {
188+
const { error } = (await response.clone().json()) as { error: string };
177189

178-
this.console.trace(`${method} ${request.url}`);
179-
return fetch(request);
190+
if (error === 'invalid_token') {
191+
this.console.info('Access token is invalid or expired.');
192+
193+
this.storage.removeItem(API.ACCESS_TOKEN);
194+
this.console.info('Removed old access token from the storage.');
195+
196+
token = await fetchNewAccessToken();
197+
198+
if (token) {
199+
request = new Request(input, init);
200+
headers = request.headers;
201+
setHeaders(token.access_token);
202+
this.console.trace(`Retrying ${method} ${request.url}`);
203+
response = await fetch(request);
204+
}
205+
}
206+
}
207+
208+
return response;
180209
}
181210
}

src/backend/Graph/store.d.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,14 @@ export interface Store extends Graph {
9999
'fx:customer_portal_settings': CustomerPortalSettings;
100100
/** POST here to resend the daily subscription webhook notification for this store. */
101101
'fx:process_subscription_webhook': ProcessSubscriptionWebhook;
102-
/** Add-to-cart URL for the Standard plan with yearly billing. */
103-
'fx:activate_store_yearly_url': { curie: 'fx:activate_store_yearly_url' };
104-
/** Add-to-cart URL for the Standard plan with monthly billing. */
105-
'fx:activate_store_monthly_url': { curie: 'fx:activate_store_monthly_url' };
102+
/** Add-to-cart URL for the Starter plan with yearly billing. */
103+
'fx:activate_store_starter_yearly_url': { curie: 'fx:activate_store_starter_yearly_url' };
104+
/** Add-to-cart URL for the Starter plan with monthly billing. */
105+
'fx:activate_store_starter_monthly_url': { curie: 'fx:activate_store_starter_monthly_url' };
106+
/** Add-to-cart URL for the Growth plan with yearly billing. */
107+
'fx:activate_store_growth_yearly_url': { curie: 'fx:activate_store_growth_yearly_url' };
108+
/** Add-to-cart URL for the Growth plan with monthly billing. */
109+
'fx:activate_store_growth_monthly_url': { curie: 'fx:activate_store_growth_monthly_url' };
106110
/** Add-to-cart URL for the Advanced plan with yearly billing. */
107111
'fx:activate_store_advanced_yearly_url': { curie: 'fx:activate_store_advanced_yearly_url' };
108112
/** Add-to-cart URL for the Advanced plan with monthly billing. */

src/backend/Graph/subscription.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ export interface Subscription extends Graph {
5555
is_active: boolean;
5656
/** If this subscription is using a third party subscription system such as PayPal Express, their identifier will be set here. */
5757
third_party_id: string;
58+
/** The type of payment method used for this subscription. Can be `null` if payment method info is unavailable via this API. */
59+
payment_type: 'plastic' | 'paypal' | 'ach' | 'amazon' | null;
5860
/** The date this resource was created. */
5961
date_created: string | null;
6062
/** The date this resource was last modified. */

src/backend/Graph/webhook.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export interface Webhook extends Graph {
3434
/** The JSON webhooks are encrypted in certain situations. This key is also used to generate a signature to verify the integrity of the payload. 1000 characters or less. */
3535
encryption_key: string | null;
3636
/** The type of resource to observe changes on. */
37-
event_resource: ('subscription' | 'transaction' | 'customer')[];
37+
event_resource: 'subscription' | 'transaction' | 'transaction_log' | 'customer';
3838
/** If set to `0`, events will not be triggered for this webhook. This can also be set to `0` automatically if there are too many consecutive failed attempts to send a payload to this endpoint. */
3939
is_active: 0 | 1;
4040
/** The date this resource was created. */

src/customer/Graph/item.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Graph } from '../../core';
2+
import type { ItemOptions } from './item_options';
23

34
export interface Item extends Graph {
45
curie: 'fx:item';
@@ -62,4 +63,8 @@ export interface Item extends Graph {
6263
/** The date this resource was last modified. */
6364
date_modified: string | null;
6465
};
66+
67+
zooms: {
68+
item_options?: ItemOptions;
69+
};
6570
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type { Graph } from '../../core';
2+
import type { Item } from './item';
3+
import type { Transaction } from './transaction';
4+
5+
export interface ItemOption extends Graph {
6+
curie: 'fx:item_option';
7+
8+
links: {
9+
/** This resource. */
10+
'self': ItemOption;
11+
/** Item this option is attached to. */
12+
'fx:item': Item;
13+
/** Related transaction resource. */
14+
'fx:transaction': Transaction;
15+
};
16+
17+
props: {
18+
/** The name of this item option. */
19+
name: string;
20+
/** The value of this item option. */
21+
value: string;
22+
/** The price modifier for this item option. The price of the item in the cart will be adjusted by this amount because of this item option. */
23+
price_mod: number;
24+
/** The weight modifier for this item option. The weight of the item in the cart will be adjusted by this amount because of this item option. */
25+
weight_mod: number;
26+
/** The date this resource was created. */
27+
date_created: string | null;
28+
/** The date this resource was last modified. */
29+
date_modified: string | null;
30+
};
31+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { CollectionGraphLinks, CollectionGraphProps } from '../../core/defaults';
2+
import type { Graph } from '../../core';
3+
import type { ItemOption } from './item_option';
4+
5+
export interface ItemOptions extends Graph {
6+
curie: 'fx:item_options';
7+
links: CollectionGraphLinks<ItemOptions>;
8+
props: CollectionGraphProps;
9+
child: ItemOption;
10+
}

src/customer/Graph/subscription.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export interface Subscription extends Graph {
4646
is_active: boolean;
4747
/** If this subscription is using a third party subscription system such as PayPal Express, their identifier will be set here. */
4848
third_party_id: string;
49+
/** The type of payment method used for this subscription. Can be `null` if payment method info is unavailable via this API. */
50+
payment_type: 'plastic' | 'paypal' | 'ach' | 'amazon' | null;
4951
/** The date this resource was created. */
5052
date_created: string | null;
5153
/** The date this resource was last modified. */

src/customer/Graph/transaction_template.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export interface TransactionTemplate extends Graph {
7474
/** If this cart has any shippable subscription items which will process in the future, this will be the total amount of shipping costs for those items. */
7575
total_future_shipping: string;
7676
/** Total order amount of this cart including all items, taxes, shipping costs and discounts. */
77-
total_order: string;
77+
total_order: number;
7878
/** The 3 character ISO code for the currency. */
7979
currency_code: string;
8080
/** The currency symbol, such as $, £, €, etc. */

src/customer/Rels.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
export * from './Graph/attribute';
22
export * from './Graph/attributes';
3+
export * from './Graph/custom_field';
4+
export * from './Graph/custom_fields';
35
export * from './Graph/customer_address';
46
export * from './Graph/customer_addresses';
57
export * from './Graph/customer_portal_settings';
68
export * from './Graph/default_billing_address';
79
export * from './Graph/default_payment_method';
810
export * from './Graph/default_shipping_address';
11+
export * from './Graph/item_option';
12+
export * from './Graph/item_options';
913
export * from './Graph/item';
1014
export * from './Graph/items';
1115
export * from './Graph/last_transaction';

0 commit comments

Comments
 (0)