@moonbase.sh/storefront-api 3.1.0 → 3.2.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 +11 -1
- package/dist/index.cjs +122 -34
- package/dist/index.d.cts +48 -1
- package/dist/index.d.ts +48 -1
- package/dist/index.js +121 -34
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -122,7 +122,17 @@ host — is returned untouched and logs a warning, since it will be served at fu
|
|
|
122
122
|
|
|
123
123
|
## Token storage and logging
|
|
124
124
|
|
|
125
|
-
By default, credentials are stored in localStorage
|
|
125
|
+
By default, credentials are stored in localStorage, falling back to memory only when localStorage
|
|
126
|
+
cannot be reached at all. Even that check sits inside a `try`, because reading
|
|
127
|
+
`window.localStorage` itself throws in Firefox when the buyer has blocked cookies and site data.
|
|
128
|
+
|
|
129
|
+
Reachability, not writability, is the test on purpose: an origin that is merely full is still
|
|
130
|
+
holding the buyer's existing session, so it is used rather than discarded. Individual reads and
|
|
131
|
+
writes that fail degrade to an in-memory copy and warn through the configured logger. The session
|
|
132
|
+
stays valid for that page load; it just doesn't survive a reload, and
|
|
133
|
+
`client.tokenStore.isPersistent` goes false once that has happened if you want to tell the buyer.
|
|
134
|
+
A failure to *persist* credentials is never reported as a failure to sign in, so a locked-down
|
|
135
|
+
browser can't strand someone in a sign-in loop.
|
|
126
136
|
|
|
127
137
|
You can inject your own storage/logger implementations:
|
|
128
138
|
|
package/dist/index.cjs
CHANGED
|
@@ -49,6 +49,7 @@ __export(index_exports, {
|
|
|
49
49
|
SubscriptionStatus: () => SubscriptionStatus,
|
|
50
50
|
TokenStore: () => TokenStore,
|
|
51
51
|
imageWidths: () => imageWidths,
|
|
52
|
+
isLocalStorageAvailable: () => isLocalStorageAvailable,
|
|
52
53
|
isPromotionDisplay: () => isPromotionDisplay,
|
|
53
54
|
isTransformableImageUrl: () => isTransformableImageUrl,
|
|
54
55
|
maxImageDimension: () => maxImageDimension,
|
|
@@ -757,15 +758,15 @@ var IdentityEndpoints = class {
|
|
|
757
758
|
throw new NotFoundError("User not found");
|
|
758
759
|
if (response.status >= 400)
|
|
759
760
|
await handleResponseProblem(response, this.logger);
|
|
761
|
+
let identity;
|
|
760
762
|
try {
|
|
761
|
-
|
|
762
|
-
const user = identitySchema.parse(data);
|
|
763
|
-
this.tokenStore.setUser(user);
|
|
764
|
-
return userSchema.parse(user);
|
|
763
|
+
identity = identitySchema.parse(await response.json());
|
|
765
764
|
} catch (err) {
|
|
766
765
|
this.logger.warn("Could not sign in user", { email, response, err });
|
|
767
766
|
throw new MoonbaseError("Bad response", "Could not sign in user", response.status);
|
|
768
767
|
}
|
|
768
|
+
this.tokenStore.setUser(identity);
|
|
769
|
+
return userSchema.parse(identity);
|
|
769
770
|
}
|
|
770
771
|
async signUp(name, email, password, address, acceptedPrivacyPolicy, acceptedTermsAndConditions, communicationOptIn) {
|
|
771
772
|
const path = `/api/customer/identity/sign-up?scheme=JWT&communicationOptIn=${communicationOptIn ? "true" : "false"}`;
|
|
@@ -792,14 +793,15 @@ var IdentityEndpoints = class {
|
|
|
792
793
|
const parsed = pendingActivationSchema.parse(data);
|
|
793
794
|
return { status: "activation-pending", email: parsed.email };
|
|
794
795
|
}
|
|
796
|
+
let identity;
|
|
795
797
|
try {
|
|
796
|
-
|
|
797
|
-
this.tokenStore.setUser(identity);
|
|
798
|
-
return { status: "signed-in", user: userSchema.parse(identity) };
|
|
798
|
+
identity = identitySchema.parse(data);
|
|
799
799
|
} catch (err) {
|
|
800
800
|
this.logger.warn("Could not sign up user", { email, response, err });
|
|
801
801
|
throw new MoonbaseError("Bad response", "Could not sign up user", response.status);
|
|
802
802
|
}
|
|
803
|
+
this.tokenStore.setUser(identity);
|
|
804
|
+
return { status: "signed-in", user: userSchema.parse(identity) };
|
|
803
805
|
}
|
|
804
806
|
async signOut() {
|
|
805
807
|
this.tokenStore.clear();
|
|
@@ -1079,6 +1081,15 @@ var MoonbaseApi = class {
|
|
|
1079
1081
|
status: response.status,
|
|
1080
1082
|
duration: finishedAt.getTime() - startedAt.getTime()
|
|
1081
1083
|
});
|
|
1084
|
+
if (response.type === "opaqueredirect" || response.status === 0) {
|
|
1085
|
+
const err = new MoonbaseError(
|
|
1086
|
+
"Unexpected redirect",
|
|
1087
|
+
`The Moonbase API redirected ${path}, which the SDK is not configured to follow`,
|
|
1088
|
+
response.status
|
|
1089
|
+
);
|
|
1090
|
+
this.reportRequestProblem(path, request, response, err);
|
|
1091
|
+
throw err;
|
|
1092
|
+
}
|
|
1082
1093
|
if (response.status >= 400) {
|
|
1083
1094
|
try {
|
|
1084
1095
|
await handleResponseProblem(response, this.logger);
|
|
@@ -1543,28 +1554,81 @@ var ConsoleLogger = class {
|
|
|
1543
1554
|
};
|
|
1544
1555
|
|
|
1545
1556
|
// src/utils/store.ts
|
|
1557
|
+
function isLocalStorageAvailable() {
|
|
1558
|
+
try {
|
|
1559
|
+
return typeof window !== "undefined" && !!window.localStorage;
|
|
1560
|
+
} catch (e) {
|
|
1561
|
+
return false;
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1546
1564
|
var LocalStorageStore = class {
|
|
1565
|
+
constructor(onDegraded) {
|
|
1566
|
+
this.onDegraded = onDegraded;
|
|
1567
|
+
// Values whose write to localStorage failed. Read back in preference to
|
|
1568
|
+
// localStorage so the rest of the session sees what it just wrote.
|
|
1569
|
+
this.fallback = /* @__PURE__ */ new Map();
|
|
1570
|
+
this.degraded = false;
|
|
1571
|
+
}
|
|
1572
|
+
get isDegraded() {
|
|
1573
|
+
return this.degraded;
|
|
1574
|
+
}
|
|
1547
1575
|
get(key) {
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1576
|
+
if (this.fallback.has(key))
|
|
1577
|
+
return this.fallback.get(key);
|
|
1578
|
+
try {
|
|
1579
|
+
const item = localStorage.getItem(key);
|
|
1580
|
+
if (item) {
|
|
1581
|
+
return JSON.parse(item);
|
|
1582
|
+
}
|
|
1583
|
+
return null;
|
|
1584
|
+
} catch (err) {
|
|
1585
|
+
this.reportDegraded(err);
|
|
1586
|
+
return null;
|
|
1551
1587
|
}
|
|
1552
|
-
return null;
|
|
1553
1588
|
}
|
|
1554
1589
|
set(key, item) {
|
|
1555
|
-
|
|
1590
|
+
try {
|
|
1591
|
+
localStorage.setItem(key, JSON.stringify(item));
|
|
1592
|
+
this.fallback.delete(key);
|
|
1593
|
+
} catch (err) {
|
|
1594
|
+
this.reportDegraded(err);
|
|
1595
|
+
this.fallback.set(key, item);
|
|
1596
|
+
}
|
|
1556
1597
|
}
|
|
1557
1598
|
remove(key) {
|
|
1558
|
-
|
|
1599
|
+
try {
|
|
1600
|
+
localStorage.removeItem(key);
|
|
1601
|
+
this.fallback.delete(key);
|
|
1602
|
+
return;
|
|
1603
|
+
} catch (err) {
|
|
1604
|
+
this.reportDegraded(err);
|
|
1605
|
+
}
|
|
1606
|
+
this.fallback.set(key, null);
|
|
1607
|
+
try {
|
|
1608
|
+
localStorage.setItem(key, "");
|
|
1609
|
+
} catch (e) {
|
|
1610
|
+
}
|
|
1559
1611
|
}
|
|
1560
1612
|
listen(key, callback) {
|
|
1561
|
-
if (typeof window
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1613
|
+
if (typeof window === "undefined")
|
|
1614
|
+
return;
|
|
1615
|
+
window.addEventListener("storage", (event) => {
|
|
1616
|
+
if (event.key !== key)
|
|
1617
|
+
return;
|
|
1618
|
+
this.fallback.delete(key);
|
|
1619
|
+
try {
|
|
1620
|
+
callback(event.newValue ? JSON.parse(event.newValue) : null);
|
|
1621
|
+
} catch (err) {
|
|
1622
|
+
console.warn(`Moonbase could not parse the stored value for ${key}`, err);
|
|
1623
|
+
}
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1626
|
+
reportDegraded(err) {
|
|
1627
|
+
var _a;
|
|
1628
|
+
if (this.degraded)
|
|
1629
|
+
return;
|
|
1630
|
+
this.degraded = true;
|
|
1631
|
+
(_a = this.onDegraded) == null ? void 0 : _a.call(this, err);
|
|
1568
1632
|
}
|
|
1569
1633
|
};
|
|
1570
1634
|
var InMemoryStore = class {
|
|
@@ -1602,8 +1666,11 @@ var _TokenStore = class _TokenStore {
|
|
|
1602
1666
|
this.tokens = null;
|
|
1603
1667
|
this.refreshTimeoutId = null;
|
|
1604
1668
|
this.refreshPromise = null;
|
|
1605
|
-
var _a;
|
|
1606
|
-
this.
|
|
1669
|
+
var _a, _b;
|
|
1670
|
+
this.logger = (_a = configuration.logger) != null ? _a : new ConsoleLogger();
|
|
1671
|
+
this.store = (_b = configuration.store) != null ? _b : isLocalStorageAvailable() ? new LocalStorageStore((err) => this.warnAboutStorage(err)) : new InMemoryStore();
|
|
1672
|
+
if (typeof window !== "undefined" && !configuration.store && !(this.store instanceof LocalStorageStore))
|
|
1673
|
+
this.warnAboutStorage();
|
|
1607
1674
|
const storedToken = this.store.get(_TokenStore.storageKey);
|
|
1608
1675
|
if (storedToken) {
|
|
1609
1676
|
this.tokens = {
|
|
@@ -1618,18 +1685,17 @@ var _TokenStore = class _TokenStore {
|
|
|
1618
1685
|
return this.tokens;
|
|
1619
1686
|
return null;
|
|
1620
1687
|
}
|
|
1688
|
+
get isPersistent() {
|
|
1689
|
+
return this.store instanceof LocalStorageStore && !this.store.isDegraded;
|
|
1690
|
+
}
|
|
1621
1691
|
async getAccessToken() {
|
|
1622
1692
|
var _a, _b, _c;
|
|
1623
|
-
if (this.isExpired) {
|
|
1624
|
-
|
|
1625
|
-
const tokens2 = await this.refreshPromise;
|
|
1626
|
-
return (_a = tokens2 == null ? void 0 : tokens2.accessToken) != null ? _a : null;
|
|
1627
|
-
}
|
|
1628
|
-
this.refreshPromise = this.refreshTokens();
|
|
1629
|
-
const tokens = await this.refreshPromise;
|
|
1630
|
-
return (_b = tokens == null ? void 0 : tokens.accessToken) != null ? _b : null;
|
|
1693
|
+
if (!this.isExpired) {
|
|
1694
|
+
return ((_a = this.tokens) == null ? void 0 : _a.accessToken) || null;
|
|
1631
1695
|
}
|
|
1632
|
-
|
|
1696
|
+
const pending = (_b = this.refreshPromise) != null ? _b : this.startRefresh();
|
|
1697
|
+
const tokens = await pending;
|
|
1698
|
+
return (_c = tokens == null ? void 0 : tokens.accessToken) != null ? _c : null;
|
|
1633
1699
|
}
|
|
1634
1700
|
setUser(user) {
|
|
1635
1701
|
const identity = user;
|
|
@@ -1654,7 +1720,7 @@ var _TokenStore = class _TokenStore {
|
|
|
1654
1720
|
if (this.refreshTimeoutId != null)
|
|
1655
1721
|
window.clearTimeout(this.refreshTimeoutId);
|
|
1656
1722
|
this.refreshTimeoutId = window.setTimeout(() => {
|
|
1657
|
-
this.
|
|
1723
|
+
this.startRefresh().catch((err) => this.logger.warn("Could not refresh access token", err));
|
|
1658
1724
|
}, 10 * 60 * 1e3);
|
|
1659
1725
|
}
|
|
1660
1726
|
return this.tokens;
|
|
@@ -1669,10 +1735,25 @@ var _TokenStore = class _TokenStore {
|
|
|
1669
1735
|
get isExpired() {
|
|
1670
1736
|
return this.tokens != null && this.tokens.expiresAt < /* @__PURE__ */ new Date();
|
|
1671
1737
|
}
|
|
1738
|
+
/**
|
|
1739
|
+
* Start a refresh and hold it so concurrent callers join it rather than firing
|
|
1740
|
+
* their own. The slot is cleared as soon as it settles: a retained promise
|
|
1741
|
+
* would hand every later expiry the same stale access token, and a rejected one
|
|
1742
|
+
* that stayed put would re-throw on every subsequent request (including the
|
|
1743
|
+
* anonymous ones) for the rest of the session.
|
|
1744
|
+
*/
|
|
1745
|
+
startRefresh() {
|
|
1746
|
+
const pending = this.refreshTokens().finally(() => {
|
|
1747
|
+
if (this.refreshPromise === pending)
|
|
1748
|
+
this.refreshPromise = null;
|
|
1749
|
+
});
|
|
1750
|
+
this.refreshPromise = pending;
|
|
1751
|
+
return pending;
|
|
1752
|
+
}
|
|
1672
1753
|
async refreshTokens() {
|
|
1673
1754
|
if (!this.tokens)
|
|
1674
1755
|
throw new Error("No tokens found to refresh");
|
|
1675
|
-
const response = await fetch(`${this.configuration.endpoint}/api/customer/identity/refresh?token=${this.tokens.refreshToken}`, {
|
|
1756
|
+
const response = await fetch(`${this.configuration.endpoint}/api/customer/identity/refresh?token=${encodeURIComponent(this.tokens.refreshToken)}`, {
|
|
1676
1757
|
method: "POST",
|
|
1677
1758
|
headers: {
|
|
1678
1759
|
"Accept": "application/json",
|
|
@@ -1694,12 +1775,18 @@ var _TokenStore = class _TokenStore {
|
|
|
1694
1775
|
}
|
|
1695
1776
|
handleStorageUpdate(updatedTokens) {
|
|
1696
1777
|
this.tokens = updatedTokens;
|
|
1697
|
-
if (this.refreshTimeoutId != null)
|
|
1778
|
+
if (this.refreshTimeoutId != null && typeof window !== "undefined")
|
|
1698
1779
|
window.clearTimeout(this.refreshTimeoutId);
|
|
1699
1780
|
if (this.tokens) {
|
|
1700
1781
|
this.tokens.expiresAt = new Date(this.tokens.expiresAt);
|
|
1701
1782
|
}
|
|
1702
1783
|
}
|
|
1784
|
+
warnAboutStorage(err) {
|
|
1785
|
+
this.logger.warn(
|
|
1786
|
+
"Moonbase could not persist credentials to localStorage: this browser is blocking or has exhausted site storage. Sign-in will work for this page load but will not survive a reload.",
|
|
1787
|
+
err
|
|
1788
|
+
);
|
|
1789
|
+
}
|
|
1703
1790
|
};
|
|
1704
1791
|
_TokenStore.storageKey = "moonbase_auth";
|
|
1705
1792
|
var TokenStore = _TokenStore;
|
|
@@ -2432,6 +2519,7 @@ var MoonbaseClient = class {
|
|
|
2432
2519
|
SubscriptionStatus,
|
|
2433
2520
|
TokenStore,
|
|
2434
2521
|
imageWidths,
|
|
2522
|
+
isLocalStorageAvailable,
|
|
2435
2523
|
isPromotionDisplay,
|
|
2436
2524
|
isTransformableImageUrl,
|
|
2437
2525
|
maxImageDimension,
|
package/dist/index.d.cts
CHANGED
|
@@ -26,12 +26,47 @@ interface IStore {
|
|
|
26
26
|
set: <TItem>(key: string, item: TItem) => void;
|
|
27
27
|
remove: (key: string) => void;
|
|
28
28
|
listen: <TItem>(key: string, callback: (item: TItem | null) => void) => void;
|
|
29
|
+
/**
|
|
30
|
+
* True once any storage operation has failed and the store has fallen back to
|
|
31
|
+
* memory. Optional so custom stores don't have to implement it.
|
|
32
|
+
*/
|
|
33
|
+
readonly isDegraded?: boolean;
|
|
29
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Whether `localStorage` can be reached at all.
|
|
37
|
+
*
|
|
38
|
+
* Deliberately *not* a write probe. Writability is not the right question here,
|
|
39
|
+
* because `LocalStorageStore` degrades per operation when a write fails, so a
|
|
40
|
+
* storage that reads fine but is at quota is still worth using: it is holding the
|
|
41
|
+
* buyer's existing session, and refusing it would throw away a perfectly readable
|
|
42
|
+
* sign-in and send them back to the login form. The only thing that makes
|
|
43
|
+
* `localStorage` unusable is not being able to touch it, which is what Firefox
|
|
44
|
+
* does (`SecurityError` from the property getter) when the buyer has blocked
|
|
45
|
+
* cookies and site data. That is why even the truthiness check sits inside a
|
|
46
|
+
* `try`.
|
|
47
|
+
*/
|
|
48
|
+
declare function isLocalStorageAvailable(): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* `localStorage`-backed store that degrades to memory instead of throwing.
|
|
51
|
+
*
|
|
52
|
+
* Storage can start failing at any point in a session, not just at construction:
|
|
53
|
+
* the origin hits quota, an extension clears site data, the profile's storage
|
|
54
|
+
* file goes corrupt. Since this is where the auth tokens live, an unhandled
|
|
55
|
+
* throw here surfaces as a failed sign-in for a buyer whose credentials were
|
|
56
|
+
* accepted. So every operation falls back to an in-memory copy. The session
|
|
57
|
+
* keeps working; it just stops surviving a reload.
|
|
58
|
+
*/
|
|
30
59
|
declare class LocalStorageStore implements IStore {
|
|
60
|
+
private readonly onDegraded?;
|
|
61
|
+
private readonly fallback;
|
|
62
|
+
private degraded;
|
|
63
|
+
constructor(onDegraded?: ((err: unknown) => void) | undefined);
|
|
64
|
+
get isDegraded(): boolean;
|
|
31
65
|
get<TItem>(key: string): TItem | null;
|
|
32
66
|
set<TItem>(key: string, item: TItem): void;
|
|
33
67
|
remove(key: string): void;
|
|
34
68
|
listen<TItem>(key: string, callback: (item: TItem | null) => void): void;
|
|
69
|
+
private reportDegraded;
|
|
35
70
|
}
|
|
36
71
|
declare class InMemoryStore implements IStore {
|
|
37
72
|
private readonly store;
|
|
@@ -47,6 +82,7 @@ type IdentityWithExpiry = Identity & {
|
|
|
47
82
|
};
|
|
48
83
|
interface ITokenStore {
|
|
49
84
|
get user(): User | null;
|
|
85
|
+
get isPersistent(): boolean;
|
|
50
86
|
getAccessToken: () => Promise<string | null>;
|
|
51
87
|
setUser: (user: Identity | User) => User | null;
|
|
52
88
|
clear: () => void;
|
|
@@ -57,15 +93,26 @@ declare class TokenStore implements ITokenStore {
|
|
|
57
93
|
private refreshTimeoutId;
|
|
58
94
|
private refreshPromise;
|
|
59
95
|
private readonly store;
|
|
96
|
+
private readonly logger;
|
|
60
97
|
static readonly storageKey = "moonbase_auth";
|
|
61
98
|
constructor(configuration: MoonbaseConfiguration);
|
|
62
99
|
get user(): User | null;
|
|
100
|
+
get isPersistent(): boolean;
|
|
63
101
|
getAccessToken(): Promise<string | null>;
|
|
64
102
|
setUser(user: Identity | User): IdentityWithExpiry | null;
|
|
65
103
|
clear(): null;
|
|
66
104
|
private get isExpired();
|
|
105
|
+
/**
|
|
106
|
+
* Start a refresh and hold it so concurrent callers join it rather than firing
|
|
107
|
+
* their own. The slot is cleared as soon as it settles: a retained promise
|
|
108
|
+
* would hand every later expiry the same stale access token, and a rejected one
|
|
109
|
+
* that stayed put would re-throw on every subsequent request (including the
|
|
110
|
+
* anonymous ones) for the rest of the session.
|
|
111
|
+
*/
|
|
112
|
+
private startRefresh;
|
|
67
113
|
private refreshTokens;
|
|
68
114
|
private handleStorageUpdate;
|
|
115
|
+
private warnAboutStorage;
|
|
69
116
|
}
|
|
70
117
|
|
|
71
118
|
type HttpMethods = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
|
@@ -47032,4 +47079,4 @@ declare class MoonbaseClient {
|
|
|
47032
47079
|
orders: OrderEndpoints;
|
|
47033
47080
|
}
|
|
47034
47081
|
|
|
47035
|
-
export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, type CartCatalog, type CartOrder, type CartTotal, type CartTotalCondition, CartUtils, type CommunicationPreferences, type CommunicationPreferencesInput, type CommunicationPreferencesView, type CompletedOrder, ConnectableAccountProvider, type ConnectedAccount, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, type ImageFit, type ImageFormat, type ImageTransform, ImageUtils, InMemoryStore, type License, LicenseStatus, type LineItem, type LineItemTotal, LocalStorageStore, LogLevel, MarketingConsentType, type MilestoneProgress, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, type OfferConditionContext, type OfferProgress, type OfferScope, OfferUtils, type OpenOrder, type Order, OrderStatus, type OrderTotal, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpResult, type SingleOrMultiple, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type Voucher, imageWidths, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
|
|
47082
|
+
export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, type CartCatalog, type CartOrder, type CartTotal, type CartTotalCondition, CartUtils, type CommunicationPreferences, type CommunicationPreferencesInput, type CommunicationPreferencesView, type CompletedOrder, ConnectableAccountProvider, type ConnectedAccount, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, type ImageFit, type ImageFormat, type ImageTransform, ImageUtils, InMemoryStore, type License, LicenseStatus, type LineItem, type LineItemTotal, LocalStorageStore, LogLevel, MarketingConsentType, type MilestoneProgress, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, type OfferConditionContext, type OfferProgress, type OfferScope, OfferUtils, type OpenOrder, type Order, OrderStatus, type OrderTotal, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpResult, type SingleOrMultiple, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type Voucher, imageWidths, isLocalStorageAvailable, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
|
package/dist/index.d.ts
CHANGED
|
@@ -26,12 +26,47 @@ interface IStore {
|
|
|
26
26
|
set: <TItem>(key: string, item: TItem) => void;
|
|
27
27
|
remove: (key: string) => void;
|
|
28
28
|
listen: <TItem>(key: string, callback: (item: TItem | null) => void) => void;
|
|
29
|
+
/**
|
|
30
|
+
* True once any storage operation has failed and the store has fallen back to
|
|
31
|
+
* memory. Optional so custom stores don't have to implement it.
|
|
32
|
+
*/
|
|
33
|
+
readonly isDegraded?: boolean;
|
|
29
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Whether `localStorage` can be reached at all.
|
|
37
|
+
*
|
|
38
|
+
* Deliberately *not* a write probe. Writability is not the right question here,
|
|
39
|
+
* because `LocalStorageStore` degrades per operation when a write fails, so a
|
|
40
|
+
* storage that reads fine but is at quota is still worth using: it is holding the
|
|
41
|
+
* buyer's existing session, and refusing it would throw away a perfectly readable
|
|
42
|
+
* sign-in and send them back to the login form. The only thing that makes
|
|
43
|
+
* `localStorage` unusable is not being able to touch it, which is what Firefox
|
|
44
|
+
* does (`SecurityError` from the property getter) when the buyer has blocked
|
|
45
|
+
* cookies and site data. That is why even the truthiness check sits inside a
|
|
46
|
+
* `try`.
|
|
47
|
+
*/
|
|
48
|
+
declare function isLocalStorageAvailable(): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* `localStorage`-backed store that degrades to memory instead of throwing.
|
|
51
|
+
*
|
|
52
|
+
* Storage can start failing at any point in a session, not just at construction:
|
|
53
|
+
* the origin hits quota, an extension clears site data, the profile's storage
|
|
54
|
+
* file goes corrupt. Since this is where the auth tokens live, an unhandled
|
|
55
|
+
* throw here surfaces as a failed sign-in for a buyer whose credentials were
|
|
56
|
+
* accepted. So every operation falls back to an in-memory copy. The session
|
|
57
|
+
* keeps working; it just stops surviving a reload.
|
|
58
|
+
*/
|
|
30
59
|
declare class LocalStorageStore implements IStore {
|
|
60
|
+
private readonly onDegraded?;
|
|
61
|
+
private readonly fallback;
|
|
62
|
+
private degraded;
|
|
63
|
+
constructor(onDegraded?: ((err: unknown) => void) | undefined);
|
|
64
|
+
get isDegraded(): boolean;
|
|
31
65
|
get<TItem>(key: string): TItem | null;
|
|
32
66
|
set<TItem>(key: string, item: TItem): void;
|
|
33
67
|
remove(key: string): void;
|
|
34
68
|
listen<TItem>(key: string, callback: (item: TItem | null) => void): void;
|
|
69
|
+
private reportDegraded;
|
|
35
70
|
}
|
|
36
71
|
declare class InMemoryStore implements IStore {
|
|
37
72
|
private readonly store;
|
|
@@ -47,6 +82,7 @@ type IdentityWithExpiry = Identity & {
|
|
|
47
82
|
};
|
|
48
83
|
interface ITokenStore {
|
|
49
84
|
get user(): User | null;
|
|
85
|
+
get isPersistent(): boolean;
|
|
50
86
|
getAccessToken: () => Promise<string | null>;
|
|
51
87
|
setUser: (user: Identity | User) => User | null;
|
|
52
88
|
clear: () => void;
|
|
@@ -57,15 +93,26 @@ declare class TokenStore implements ITokenStore {
|
|
|
57
93
|
private refreshTimeoutId;
|
|
58
94
|
private refreshPromise;
|
|
59
95
|
private readonly store;
|
|
96
|
+
private readonly logger;
|
|
60
97
|
static readonly storageKey = "moonbase_auth";
|
|
61
98
|
constructor(configuration: MoonbaseConfiguration);
|
|
62
99
|
get user(): User | null;
|
|
100
|
+
get isPersistent(): boolean;
|
|
63
101
|
getAccessToken(): Promise<string | null>;
|
|
64
102
|
setUser(user: Identity | User): IdentityWithExpiry | null;
|
|
65
103
|
clear(): null;
|
|
66
104
|
private get isExpired();
|
|
105
|
+
/**
|
|
106
|
+
* Start a refresh and hold it so concurrent callers join it rather than firing
|
|
107
|
+
* their own. The slot is cleared as soon as it settles: a retained promise
|
|
108
|
+
* would hand every later expiry the same stale access token, and a rejected one
|
|
109
|
+
* that stayed put would re-throw on every subsequent request (including the
|
|
110
|
+
* anonymous ones) for the rest of the session.
|
|
111
|
+
*/
|
|
112
|
+
private startRefresh;
|
|
67
113
|
private refreshTokens;
|
|
68
114
|
private handleStorageUpdate;
|
|
115
|
+
private warnAboutStorage;
|
|
69
116
|
}
|
|
70
117
|
|
|
71
118
|
type HttpMethods = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
|
@@ -47032,4 +47079,4 @@ declare class MoonbaseClient {
|
|
|
47032
47079
|
orders: OrderEndpoints;
|
|
47033
47080
|
}
|
|
47034
47081
|
|
|
47035
|
-
export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, type CartCatalog, type CartOrder, type CartTotal, type CartTotalCondition, CartUtils, type CommunicationPreferences, type CommunicationPreferencesInput, type CommunicationPreferencesView, type CompletedOrder, ConnectableAccountProvider, type ConnectedAccount, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, type ImageFit, type ImageFormat, type ImageTransform, ImageUtils, InMemoryStore, type License, LicenseStatus, type LineItem, type LineItemTotal, LocalStorageStore, LogLevel, MarketingConsentType, type MilestoneProgress, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, type OfferConditionContext, type OfferProgress, type OfferScope, OfferUtils, type OpenOrder, type Order, OrderStatus, type OrderTotal, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpResult, type SingleOrMultiple, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type Voucher, imageWidths, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
|
|
47082
|
+
export { type Activation, ActivationMethod, type ActivationRequest, ActivationRequestFulfillmentType, ActivationRequestStatus, ActivationStatus, type Address, Architecture, type BundleLineItem, type CartCatalog, type CartOrder, type CartTotal, type CartTotalCondition, CartUtils, type CommunicationPreferences, type CommunicationPreferencesInput, type CommunicationPreferencesView, type CompletedOrder, ConnectableAccountProvider, type ConnectedAccount, ConsoleLogger, CycleLength, type Discount, DiscountUtils, type Download, type DownloadManifest, type ILogger, type IRecurrence, type IStore, type ITokenStore, type Identity, type ImageFit, type ImageFormat, type ImageTransform, ImageUtils, InMemoryStore, type License, LicenseStatus, type LineItem, type LineItemTotal, LocalStorageStore, LogLevel, MarketingConsentType, type MilestoneProgress, type Money, type MoneyCollection, MoneyCollectionUtils, MoonbaseApi, MoonbaseClient, type MoonbaseConfiguration, MoonbaseError, NotAuthenticatedError, NotAuthorizedError, NotFoundError, type OfferCondition, type OfferConditionContext, type OfferProgress, type OfferScope, OfferUtils, type OpenOrder, type Order, OrderStatus, type OrderTotal, type OwnedProduct, type Page, Platform, type PricingTier, type PricingVariation, type ProblemDetails, type ProductLineItem, type PromotionDisplay, type Quantifiable, type RawPropertyArray, type RawPropertyObject, type RawPropertyValue, type SignUpResult, type SingleOrMultiple, type Storefront, type StorefrontBundle, type StorefrontOffer, type StorefrontOfferTarget, type StorefrontProduct, type StorefrontPromotion, type StorefrontPromotionCta, type StorefrontPromotionTarget, type SubscribeInput, type SubscribeResponse, type Subscription, SubscriptionStatus, type TaxEstimate, TokenStore, type UrchinTrackingModule, type User, type UserAccountConfirmed, type UserAccountConfirmedStatus, type Vendor, type Voucher, imageWidths, isLocalStorageAvailable, isPromotionDisplay, isTransformableImageUrl, maxImageDimension, objectToQuery, parseOffSiteReferrer, problemDetailsSchema, promotionDisplays, resolveUtm, schemas, utmToObject };
|
package/dist/index.js
CHANGED
|
@@ -699,15 +699,15 @@ var IdentityEndpoints = class {
|
|
|
699
699
|
throw new NotFoundError("User not found");
|
|
700
700
|
if (response.status >= 400)
|
|
701
701
|
await handleResponseProblem(response, this.logger);
|
|
702
|
+
let identity;
|
|
702
703
|
try {
|
|
703
|
-
|
|
704
|
-
const user = identitySchema.parse(data);
|
|
705
|
-
this.tokenStore.setUser(user);
|
|
706
|
-
return userSchema.parse(user);
|
|
704
|
+
identity = identitySchema.parse(await response.json());
|
|
707
705
|
} catch (err) {
|
|
708
706
|
this.logger.warn("Could not sign in user", { email, response, err });
|
|
709
707
|
throw new MoonbaseError("Bad response", "Could not sign in user", response.status);
|
|
710
708
|
}
|
|
709
|
+
this.tokenStore.setUser(identity);
|
|
710
|
+
return userSchema.parse(identity);
|
|
711
711
|
}
|
|
712
712
|
async signUp(name, email, password, address, acceptedPrivacyPolicy, acceptedTermsAndConditions, communicationOptIn) {
|
|
713
713
|
const path = `/api/customer/identity/sign-up?scheme=JWT&communicationOptIn=${communicationOptIn ? "true" : "false"}`;
|
|
@@ -734,14 +734,15 @@ var IdentityEndpoints = class {
|
|
|
734
734
|
const parsed = pendingActivationSchema.parse(data);
|
|
735
735
|
return { status: "activation-pending", email: parsed.email };
|
|
736
736
|
}
|
|
737
|
+
let identity;
|
|
737
738
|
try {
|
|
738
|
-
|
|
739
|
-
this.tokenStore.setUser(identity);
|
|
740
|
-
return { status: "signed-in", user: userSchema.parse(identity) };
|
|
739
|
+
identity = identitySchema.parse(data);
|
|
741
740
|
} catch (err) {
|
|
742
741
|
this.logger.warn("Could not sign up user", { email, response, err });
|
|
743
742
|
throw new MoonbaseError("Bad response", "Could not sign up user", response.status);
|
|
744
743
|
}
|
|
744
|
+
this.tokenStore.setUser(identity);
|
|
745
|
+
return { status: "signed-in", user: userSchema.parse(identity) };
|
|
745
746
|
}
|
|
746
747
|
async signOut() {
|
|
747
748
|
this.tokenStore.clear();
|
|
@@ -1021,6 +1022,15 @@ var MoonbaseApi = class {
|
|
|
1021
1022
|
status: response.status,
|
|
1022
1023
|
duration: finishedAt.getTime() - startedAt.getTime()
|
|
1023
1024
|
});
|
|
1025
|
+
if (response.type === "opaqueredirect" || response.status === 0) {
|
|
1026
|
+
const err = new MoonbaseError(
|
|
1027
|
+
"Unexpected redirect",
|
|
1028
|
+
`The Moonbase API redirected ${path}, which the SDK is not configured to follow`,
|
|
1029
|
+
response.status
|
|
1030
|
+
);
|
|
1031
|
+
this.reportRequestProblem(path, request, response, err);
|
|
1032
|
+
throw err;
|
|
1033
|
+
}
|
|
1024
1034
|
if (response.status >= 400) {
|
|
1025
1035
|
try {
|
|
1026
1036
|
await handleResponseProblem(response, this.logger);
|
|
@@ -1485,28 +1495,81 @@ var ConsoleLogger = class {
|
|
|
1485
1495
|
};
|
|
1486
1496
|
|
|
1487
1497
|
// src/utils/store.ts
|
|
1498
|
+
function isLocalStorageAvailable() {
|
|
1499
|
+
try {
|
|
1500
|
+
return typeof window !== "undefined" && !!window.localStorage;
|
|
1501
|
+
} catch (e) {
|
|
1502
|
+
return false;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1488
1505
|
var LocalStorageStore = class {
|
|
1506
|
+
constructor(onDegraded) {
|
|
1507
|
+
this.onDegraded = onDegraded;
|
|
1508
|
+
// Values whose write to localStorage failed. Read back in preference to
|
|
1509
|
+
// localStorage so the rest of the session sees what it just wrote.
|
|
1510
|
+
this.fallback = /* @__PURE__ */ new Map();
|
|
1511
|
+
this.degraded = false;
|
|
1512
|
+
}
|
|
1513
|
+
get isDegraded() {
|
|
1514
|
+
return this.degraded;
|
|
1515
|
+
}
|
|
1489
1516
|
get(key) {
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1517
|
+
if (this.fallback.has(key))
|
|
1518
|
+
return this.fallback.get(key);
|
|
1519
|
+
try {
|
|
1520
|
+
const item = localStorage.getItem(key);
|
|
1521
|
+
if (item) {
|
|
1522
|
+
return JSON.parse(item);
|
|
1523
|
+
}
|
|
1524
|
+
return null;
|
|
1525
|
+
} catch (err) {
|
|
1526
|
+
this.reportDegraded(err);
|
|
1527
|
+
return null;
|
|
1493
1528
|
}
|
|
1494
|
-
return null;
|
|
1495
1529
|
}
|
|
1496
1530
|
set(key, item) {
|
|
1497
|
-
|
|
1531
|
+
try {
|
|
1532
|
+
localStorage.setItem(key, JSON.stringify(item));
|
|
1533
|
+
this.fallback.delete(key);
|
|
1534
|
+
} catch (err) {
|
|
1535
|
+
this.reportDegraded(err);
|
|
1536
|
+
this.fallback.set(key, item);
|
|
1537
|
+
}
|
|
1498
1538
|
}
|
|
1499
1539
|
remove(key) {
|
|
1500
|
-
|
|
1540
|
+
try {
|
|
1541
|
+
localStorage.removeItem(key);
|
|
1542
|
+
this.fallback.delete(key);
|
|
1543
|
+
return;
|
|
1544
|
+
} catch (err) {
|
|
1545
|
+
this.reportDegraded(err);
|
|
1546
|
+
}
|
|
1547
|
+
this.fallback.set(key, null);
|
|
1548
|
+
try {
|
|
1549
|
+
localStorage.setItem(key, "");
|
|
1550
|
+
} catch (e) {
|
|
1551
|
+
}
|
|
1501
1552
|
}
|
|
1502
1553
|
listen(key, callback) {
|
|
1503
|
-
if (typeof window
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1554
|
+
if (typeof window === "undefined")
|
|
1555
|
+
return;
|
|
1556
|
+
window.addEventListener("storage", (event) => {
|
|
1557
|
+
if (event.key !== key)
|
|
1558
|
+
return;
|
|
1559
|
+
this.fallback.delete(key);
|
|
1560
|
+
try {
|
|
1561
|
+
callback(event.newValue ? JSON.parse(event.newValue) : null);
|
|
1562
|
+
} catch (err) {
|
|
1563
|
+
console.warn(`Moonbase could not parse the stored value for ${key}`, err);
|
|
1564
|
+
}
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
reportDegraded(err) {
|
|
1568
|
+
var _a;
|
|
1569
|
+
if (this.degraded)
|
|
1570
|
+
return;
|
|
1571
|
+
this.degraded = true;
|
|
1572
|
+
(_a = this.onDegraded) == null ? void 0 : _a.call(this, err);
|
|
1510
1573
|
}
|
|
1511
1574
|
};
|
|
1512
1575
|
var InMemoryStore = class {
|
|
@@ -1544,8 +1607,11 @@ var _TokenStore = class _TokenStore {
|
|
|
1544
1607
|
this.tokens = null;
|
|
1545
1608
|
this.refreshTimeoutId = null;
|
|
1546
1609
|
this.refreshPromise = null;
|
|
1547
|
-
var _a;
|
|
1548
|
-
this.
|
|
1610
|
+
var _a, _b;
|
|
1611
|
+
this.logger = (_a = configuration.logger) != null ? _a : new ConsoleLogger();
|
|
1612
|
+
this.store = (_b = configuration.store) != null ? _b : isLocalStorageAvailable() ? new LocalStorageStore((err) => this.warnAboutStorage(err)) : new InMemoryStore();
|
|
1613
|
+
if (typeof window !== "undefined" && !configuration.store && !(this.store instanceof LocalStorageStore))
|
|
1614
|
+
this.warnAboutStorage();
|
|
1549
1615
|
const storedToken = this.store.get(_TokenStore.storageKey);
|
|
1550
1616
|
if (storedToken) {
|
|
1551
1617
|
this.tokens = {
|
|
@@ -1560,18 +1626,17 @@ var _TokenStore = class _TokenStore {
|
|
|
1560
1626
|
return this.tokens;
|
|
1561
1627
|
return null;
|
|
1562
1628
|
}
|
|
1629
|
+
get isPersistent() {
|
|
1630
|
+
return this.store instanceof LocalStorageStore && !this.store.isDegraded;
|
|
1631
|
+
}
|
|
1563
1632
|
async getAccessToken() {
|
|
1564
1633
|
var _a, _b, _c;
|
|
1565
|
-
if (this.isExpired) {
|
|
1566
|
-
|
|
1567
|
-
const tokens2 = await this.refreshPromise;
|
|
1568
|
-
return (_a = tokens2 == null ? void 0 : tokens2.accessToken) != null ? _a : null;
|
|
1569
|
-
}
|
|
1570
|
-
this.refreshPromise = this.refreshTokens();
|
|
1571
|
-
const tokens = await this.refreshPromise;
|
|
1572
|
-
return (_b = tokens == null ? void 0 : tokens.accessToken) != null ? _b : null;
|
|
1634
|
+
if (!this.isExpired) {
|
|
1635
|
+
return ((_a = this.tokens) == null ? void 0 : _a.accessToken) || null;
|
|
1573
1636
|
}
|
|
1574
|
-
|
|
1637
|
+
const pending = (_b = this.refreshPromise) != null ? _b : this.startRefresh();
|
|
1638
|
+
const tokens = await pending;
|
|
1639
|
+
return (_c = tokens == null ? void 0 : tokens.accessToken) != null ? _c : null;
|
|
1575
1640
|
}
|
|
1576
1641
|
setUser(user) {
|
|
1577
1642
|
const identity = user;
|
|
@@ -1596,7 +1661,7 @@ var _TokenStore = class _TokenStore {
|
|
|
1596
1661
|
if (this.refreshTimeoutId != null)
|
|
1597
1662
|
window.clearTimeout(this.refreshTimeoutId);
|
|
1598
1663
|
this.refreshTimeoutId = window.setTimeout(() => {
|
|
1599
|
-
this.
|
|
1664
|
+
this.startRefresh().catch((err) => this.logger.warn("Could not refresh access token", err));
|
|
1600
1665
|
}, 10 * 60 * 1e3);
|
|
1601
1666
|
}
|
|
1602
1667
|
return this.tokens;
|
|
@@ -1611,10 +1676,25 @@ var _TokenStore = class _TokenStore {
|
|
|
1611
1676
|
get isExpired() {
|
|
1612
1677
|
return this.tokens != null && this.tokens.expiresAt < /* @__PURE__ */ new Date();
|
|
1613
1678
|
}
|
|
1679
|
+
/**
|
|
1680
|
+
* Start a refresh and hold it so concurrent callers join it rather than firing
|
|
1681
|
+
* their own. The slot is cleared as soon as it settles: a retained promise
|
|
1682
|
+
* would hand every later expiry the same stale access token, and a rejected one
|
|
1683
|
+
* that stayed put would re-throw on every subsequent request (including the
|
|
1684
|
+
* anonymous ones) for the rest of the session.
|
|
1685
|
+
*/
|
|
1686
|
+
startRefresh() {
|
|
1687
|
+
const pending = this.refreshTokens().finally(() => {
|
|
1688
|
+
if (this.refreshPromise === pending)
|
|
1689
|
+
this.refreshPromise = null;
|
|
1690
|
+
});
|
|
1691
|
+
this.refreshPromise = pending;
|
|
1692
|
+
return pending;
|
|
1693
|
+
}
|
|
1614
1694
|
async refreshTokens() {
|
|
1615
1695
|
if (!this.tokens)
|
|
1616
1696
|
throw new Error("No tokens found to refresh");
|
|
1617
|
-
const response = await fetch(`${this.configuration.endpoint}/api/customer/identity/refresh?token=${this.tokens.refreshToken}`, {
|
|
1697
|
+
const response = await fetch(`${this.configuration.endpoint}/api/customer/identity/refresh?token=${encodeURIComponent(this.tokens.refreshToken)}`, {
|
|
1618
1698
|
method: "POST",
|
|
1619
1699
|
headers: {
|
|
1620
1700
|
"Accept": "application/json",
|
|
@@ -1636,12 +1716,18 @@ var _TokenStore = class _TokenStore {
|
|
|
1636
1716
|
}
|
|
1637
1717
|
handleStorageUpdate(updatedTokens) {
|
|
1638
1718
|
this.tokens = updatedTokens;
|
|
1639
|
-
if (this.refreshTimeoutId != null)
|
|
1719
|
+
if (this.refreshTimeoutId != null && typeof window !== "undefined")
|
|
1640
1720
|
window.clearTimeout(this.refreshTimeoutId);
|
|
1641
1721
|
if (this.tokens) {
|
|
1642
1722
|
this.tokens.expiresAt = new Date(this.tokens.expiresAt);
|
|
1643
1723
|
}
|
|
1644
1724
|
}
|
|
1725
|
+
warnAboutStorage(err) {
|
|
1726
|
+
this.logger.warn(
|
|
1727
|
+
"Moonbase could not persist credentials to localStorage: this browser is blocking or has exhausted site storage. Sign-in will work for this page load but will not survive a reload.",
|
|
1728
|
+
err
|
|
1729
|
+
);
|
|
1730
|
+
}
|
|
1645
1731
|
};
|
|
1646
1732
|
_TokenStore.storageKey = "moonbase_auth";
|
|
1647
1733
|
var TokenStore = _TokenStore;
|
|
@@ -2373,6 +2459,7 @@ export {
|
|
|
2373
2459
|
SubscriptionStatus,
|
|
2374
2460
|
TokenStore,
|
|
2375
2461
|
imageWidths,
|
|
2462
|
+
isLocalStorageAvailable,
|
|
2376
2463
|
isPromotionDisplay,
|
|
2377
2464
|
isTransformableImageUrl,
|
|
2378
2465
|
maxImageDimension,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moonbase.sh/storefront-api",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.2.0",
|
|
5
5
|
"description": "Package to let you build storefronts with Moonbase.sh as payment and delivery provider",
|
|
6
6
|
"author": "Tobias Lønnerød Madsen <m@dsen.tv>",
|
|
7
7
|
"license": "MIT",
|