@doswiftly/storefront-sdk 21.0.1 → 22.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 22.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 49139e2: Remove the `pendingPoints` field from `LoyaltyPointsSummary` (GraphQL schema, the `LoyaltyPointsSummary` fragment and the generated types). The field was never populated — it always returned `0` — because purchase points are credited directly when the payment is captured, so there is no "pending" state to report.
8
+
9
+ **Migration:** if your storefront reads `points.pendingPoints` (or selects `pendingPoints` in a custom query or fragment), remove that usage and re-run your codegen. No replacement field is needed — `currentPoints` has always been the spendable balance.
10
+
11
+ ### Minor Changes
12
+
13
+ - 49139e2: Referral program signup support — the loyalty referral program now works end-to-end:
14
+ - `customerSignup` accepts an optional `referralCode` in its input. When the shop's referral program is active, a valid code grants the configured bonus points to the new customer and, after their first paid order, rewards the referrer. An invalid, expired or own code is silently ignored — the signup always succeeds.
15
+ - New referral capture helpers in the SDK: `useReferralCapture()` / `captureReferralCode()` persist the `?ref=CODE` parameter from a referral landing link into the readable `referral-code` cookie (30 days by default), and `readReferralCodeCookie()` / `clearReferralCodeCookie()` read and clear it at signup time. A server-side `readReferralCodeCookie()` is available from `@doswiftly/storefront-sdk/react/server` for SSR-rendered signup forms. Core constants and the URL extractor (`REFERRAL_COOKIE_NAME`, `REFERRAL_COOKIE_MAX_AGE`, `extractReferralCodeFromUrl`) are exported from the framework-agnostic core entry.
16
+
17
+ The cookie lifetime is the _landing → signup_ window and is intentionally independent of the shop's referral validity setting, which starts at signup and is enforced by the API.
18
+
3
19
  ## 21.0.1
4
20
 
5
21
  ### Patch Changes
package/README.md CHANGED
@@ -667,6 +667,50 @@ const {
667
667
  });
668
668
  ```
669
669
 
670
+ ## Referral program
671
+
672
+ When the shop's loyalty referral program is enabled, customers share links like
673
+ `https://shop.example/register?ref=REF-AB12CD34` (the code and share URL come
674
+ from the `referralStats` / `loyaltyGenerateReferralCode` GraphQL operations).
675
+ The SDK bridges the gap between landing on such a link and the actual signup:
676
+
677
+ ```tsx
678
+ // 1. Capture the code on landing — mount once near the top of the app.
679
+ 'use client';
680
+ import { useReferralCapture } from '@doswiftly/storefront-sdk/react';
681
+
682
+ export function ReferralCapture() {
683
+ useReferralCapture(); // reads ?ref=... and stores it in the `referral-code` cookie (30 days)
684
+ return null;
685
+ }
686
+ ```
687
+
688
+ ```tsx
689
+ // 2. At signup, pass the stored code in the customerSignup input and clear it on success.
690
+ import { getReferralCodeCookie, clearReferralCodeCookie } from '@doswiftly/storefront-sdk/react';
691
+
692
+ const referralCode = getReferralCodeCookie();
693
+ await signup({ email, password, firstName, lastName, referralCode: referralCode ?? undefined });
694
+ clearReferralCodeCookie();
695
+ ```
696
+
697
+ Codes are case-insensitive and an invalid, malformed, expired or own code is
698
+ silently ignored by the API — the signup always succeeds. The capture step only
699
+ persists values matching the platform code shape (letters, digits, dashes —
700
+ `REFERRAL_CODE_PATTERN`), so junk `?ref=` values never reach the cookie. Server
701
+ Components can read the stored code with the async `readReferralCodeCookie()`
702
+ from `@doswiftly/storefront-sdk/react/server` (e.g. to pre-fill an SSR-rendered
703
+ form) — note the deliberate naming split: synchronous `getReferralCodeCookie()`
704
+ on the client entry vs server-first `readReferralCodeCookie()` on the server
705
+ entry. Non-React runtimes can use the core helpers directly:
706
+ `extractReferralCodeFromUrl(url)` plus the `REFERRAL_COOKIE_NAME` /
707
+ `REFERRAL_COOKIE_MAX_AGE` constants.
708
+
709
+ The cookie lifetime (30 days, override via `captureReferralCode({ maxAge })`)
710
+ is the *landing → signup* window. It is independent of the shop's referral
711
+ validity setting — that one starts at signup, limits the time the referred
712
+ customer has to place their first order, and is enforced by the backend.
713
+
670
714
  ## Pre-built React components
671
715
 
672
716
  Headless, accessibility-aware, zero styling — pass `className` to integrate with
@@ -1553,6 +1553,8 @@ export type CustomerCreateInput = {
1553
1553
  password: Scalars['String']['input'];
1554
1554
  /** Phone number (free-form). */
1555
1555
  phone?: InputMaybe<Scalars['String']['input']>;
1556
+ /** Referral code of an existing customer, usually taken from a referral link's `ref` URL parameter (codes are case-insensitive). Optional — an invalid, malformed, expired or own code is silently ignored and the signup still succeeds; only a value longer than 50 characters is rejected. When the shop's referral program is active, a valid code grants the configured bonus points to the new customer and, after their first paid order, rewards the referrer. */
1557
+ referralCode?: InputMaybe<Scalars['String']['input']>;
1556
1558
  };
1557
1559
  export type CustomerGroup = {
1558
1560
  /** Group code */
@@ -2092,8 +2094,6 @@ export type LoyaltyPointsSummary = {
2092
2094
  expiringPoints?: Maybe<Scalars['Int']['output']>;
2093
2095
  /** Next expiry date (ISO 8601) */
2094
2096
  nextExpiryDate?: Maybe<Scalars['DateTime']['output']>;
2095
- /** Points pending (from incomplete orders) */
2096
- pendingPoints: Scalars['Int']['output'];
2097
2097
  /** Points redeemed */
2098
2098
  redeemedPoints: Scalars['Int']['output'];
2099
2099
  /** Total points earned all-time */