@spree/next 0.6.9 → 0.7.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/dist/actions/addresses.d.ts +5 -5
- package/dist/actions/addresses.js +9 -9
- package/dist/actions/addresses.js.map +1 -1
- package/dist/actions/auth.d.ts +3 -3
- package/dist/actions/auth.js +10 -10
- package/dist/actions/auth.js.map +1 -1
- package/dist/actions/cart.d.ts +7 -7
- package/dist/actions/cart.js +10 -10
- package/dist/actions/cart.js.map +1 -1
- package/dist/actions/checkout.d.ts +10 -10
- package/dist/actions/checkout.js +11 -11
- package/dist/actions/checkout.js.map +1 -1
- package/dist/actions/credit-cards.d.ts +2 -2
- package/dist/actions/credit-cards.js +6 -6
- package/dist/actions/credit-cards.js.map +1 -1
- package/dist/actions/gift-cards.d.ts +3 -3
- package/dist/actions/gift-cards.js +6 -6
- package/dist/actions/gift-cards.js.map +1 -1
- package/dist/actions/locale.js +2 -2
- package/dist/actions/locale.js.map +1 -1
- package/dist/actions/orders.d.ts +3 -3
- package/dist/actions/orders.js +6 -6
- package/dist/actions/orders.js.map +1 -1
- package/dist/actions/payment-sessions.d.ts +5 -5
- package/dist/actions/payment-sessions.js +6 -6
- package/dist/actions/payment-sessions.js.map +1 -1
- package/dist/actions/payment-setup-sessions.d.ts +4 -4
- package/dist/actions/payment-setup-sessions.js +7 -7
- package/dist/actions/payment-setup-sessions.js.map +1 -1
- package/dist/config.d.ts +3 -3
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/data/countries.d.ts +3 -3
- package/dist/data/countries.js +4 -4
- package/dist/data/countries.js.map +1 -1
- package/dist/data/currencies.d.ts +2 -2
- package/dist/data/currencies.js +3 -3
- package/dist/data/currencies.js.map +1 -1
- package/dist/data/locales.d.ts +2 -2
- package/dist/data/locales.js +3 -3
- package/dist/data/locales.js.map +1 -1
- package/dist/data/markets.d.ts +6 -6
- package/dist/data/markets.js +7 -7
- package/dist/data/markets.js.map +1 -1
- package/dist/data/products.d.ts +3 -3
- package/dist/data/products.js +5 -5
- package/dist/data/products.js.map +1 -1
- package/dist/data/taxonomies.d.ts +3 -3
- package/dist/data/taxonomies.js +4 -4
- package/dist/data/taxonomies.js.map +1 -1
- package/dist/data/taxons.d.ts +4 -4
- package/dist/data/taxons.js +5 -5
- package/dist/data/taxons.js.map +1 -1
- package/dist/index.d.ts +35 -35
- package/dist/index.js +62 -62
- package/dist/index.js.map +1 -1
- package/dist/locale.js +2 -2
- package/dist/locale.js.map +1 -1
- package/package.json +2 -2
package/dist/actions/checkout.js
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
import { revalidateTag } from "next/cache";
|
|
5
5
|
|
|
6
6
|
// src/config.ts
|
|
7
|
-
import {
|
|
7
|
+
import { createClient } from "@spree/sdk";
|
|
8
8
|
var _client = null;
|
|
9
9
|
var _config = null;
|
|
10
10
|
function initSpreeNext(config) {
|
|
11
11
|
_config = config;
|
|
12
|
-
_client =
|
|
12
|
+
_client = createClient({
|
|
13
13
|
baseUrl: config.baseUrl,
|
|
14
14
|
publishableKey: config.publishableKey
|
|
15
15
|
});
|
|
@@ -72,7 +72,7 @@ async function getCheckoutOptions() {
|
|
|
72
72
|
}
|
|
73
73
|
async function getCheckout(orderId) {
|
|
74
74
|
const options = await getCheckoutOptions();
|
|
75
|
-
return getClient().
|
|
75
|
+
return getClient().orders.get(
|
|
76
76
|
orderId,
|
|
77
77
|
{ expand: ["line_items", "shipments", "ship_address", "bill_address"] },
|
|
78
78
|
options
|
|
@@ -80,29 +80,29 @@ async function getCheckout(orderId) {
|
|
|
80
80
|
}
|
|
81
81
|
async function updateOrder(orderId, params) {
|
|
82
82
|
const options = await getCheckoutOptions();
|
|
83
|
-
const result = await getClient().
|
|
83
|
+
const result = await getClient().orders.update(orderId, params, options);
|
|
84
84
|
revalidateTag("checkout");
|
|
85
85
|
return result;
|
|
86
86
|
}
|
|
87
87
|
async function advance(orderId) {
|
|
88
88
|
const options = await getCheckoutOptions();
|
|
89
|
-
const result = await getClient().
|
|
89
|
+
const result = await getClient().orders.advance(orderId, options);
|
|
90
90
|
revalidateTag("checkout");
|
|
91
91
|
return result;
|
|
92
92
|
}
|
|
93
93
|
async function next(orderId) {
|
|
94
94
|
const options = await getCheckoutOptions();
|
|
95
|
-
const result = await getClient().
|
|
95
|
+
const result = await getClient().orders.next(orderId, options);
|
|
96
96
|
revalidateTag("checkout");
|
|
97
97
|
return result;
|
|
98
98
|
}
|
|
99
99
|
async function getShipments(orderId) {
|
|
100
100
|
const options = await getCheckoutOptions();
|
|
101
|
-
return getClient().
|
|
101
|
+
return getClient().orders.shipments.list(orderId, options);
|
|
102
102
|
}
|
|
103
103
|
async function selectShippingRate(orderId, shipmentId, shippingRateId) {
|
|
104
104
|
const options = await getCheckoutOptions();
|
|
105
|
-
const result = await getClient().
|
|
105
|
+
const result = await getClient().orders.shipments.update(
|
|
106
106
|
orderId,
|
|
107
107
|
shipmentId,
|
|
108
108
|
{ selected_shipping_rate_id: shippingRateId },
|
|
@@ -113,21 +113,21 @@ async function selectShippingRate(orderId, shipmentId, shippingRateId) {
|
|
|
113
113
|
}
|
|
114
114
|
async function applyCoupon(orderId, code) {
|
|
115
115
|
const options = await getCheckoutOptions();
|
|
116
|
-
const result = await getClient().
|
|
116
|
+
const result = await getClient().orders.couponCodes.apply(orderId, code, options);
|
|
117
117
|
revalidateTag("checkout");
|
|
118
118
|
revalidateTag("cart");
|
|
119
119
|
return result;
|
|
120
120
|
}
|
|
121
121
|
async function removeCoupon(orderId, promotionId) {
|
|
122
122
|
const options = await getCheckoutOptions();
|
|
123
|
-
const result = await getClient().
|
|
123
|
+
const result = await getClient().orders.couponCodes.remove(orderId, promotionId, options);
|
|
124
124
|
revalidateTag("checkout");
|
|
125
125
|
revalidateTag("cart");
|
|
126
126
|
return result;
|
|
127
127
|
}
|
|
128
128
|
async function complete(orderId) {
|
|
129
129
|
const options = await getCheckoutOptions();
|
|
130
|
-
const result = await getClient().
|
|
130
|
+
const result = await getClient().orders.complete(orderId, options);
|
|
131
131
|
revalidateTag("checkout");
|
|
132
132
|
revalidateTag("cart");
|
|
133
133
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/actions/checkout.ts","../../src/config.ts","../../src/cookies.ts"],"sourcesContent":["'use server';\n\nimport { revalidateTag } from 'next/cache';\nimport type { StoreOrder, StoreShipment, UpdateOrderParams } from '@spree/sdk';\nimport { getClient } from '../config';\nimport { getCartToken, getAccessToken } from '../cookies';\n\nasync function getCheckoutOptions() {\n const orderToken = await getCartToken();\n const token = await getAccessToken();\n return { orderToken, token };\n}\n\n/**\n * Get the current checkout order state.\n * Includes line_items, shipments, and addresses by default.\n */\nexport async function getCheckout(\n orderId: string\n): Promise<StoreOrder> {\n const options = await getCheckoutOptions();\n return getClient().store.orders.get(\n orderId,\n { expand: ['line_items', 'shipments', 'ship_address', 'bill_address'] },\n options\n );\n}\n\n/**\n * Update an order (addresses, email, currency, locale, metadata, etc.).\n */\nexport async function updateOrder(\n orderId: string,\n params: UpdateOrderParams\n): Promise<StoreOrder> {\n const options = await getCheckoutOptions();\n const result = await getClient().store.orders.update(orderId, params, options);\n revalidateTag('checkout');\n return result;\n}\n\n/**\n * Advance the checkout to the next step.\n */\nexport async function advance(orderId: string): Promise<StoreOrder> {\n const options = await getCheckoutOptions();\n const result = await getClient().store.orders.advance(orderId, options);\n revalidateTag('checkout');\n return result;\n}\n\n/**\n * Move the checkout to the next step (alias for advance).\n */\nexport async function next(orderId: string): Promise<StoreOrder> {\n const options = await getCheckoutOptions();\n const result = await getClient().store.orders.next(orderId, options);\n revalidateTag('checkout');\n return result;\n}\n\n/**\n * Get shipments for the order (includes available shipping rates).\n */\nexport async function getShipments(\n orderId: string\n): Promise<{ data: StoreShipment[] }> {\n const options = await getCheckoutOptions();\n return getClient().store.orders.shipments.list(orderId, options);\n}\n\n/**\n * Select a shipping rate for a shipment.\n * Returns the updated order with recalculated totals.\n */\nexport async function selectShippingRate(\n orderId: string,\n shipmentId: string,\n shippingRateId: string\n): Promise<StoreOrder> {\n const options = await getCheckoutOptions();\n const result = await getClient().store.orders.shipments.update(\n orderId,\n shipmentId,\n { selected_shipping_rate_id: shippingRateId },\n options\n );\n revalidateTag('checkout');\n return result;\n}\n\n/**\n * Apply a coupon code to the order.\n */\nexport async function applyCoupon(\n orderId: string,\n code: string\n): Promise<StoreOrder> {\n const options = await getCheckoutOptions();\n const result = await getClient().store.orders.couponCodes.apply(orderId, code, options);\n revalidateTag('checkout');\n revalidateTag('cart');\n return result;\n}\n\n/**\n * Remove a coupon/promotion from the order.\n */\nexport async function removeCoupon(\n orderId: string,\n promotionId: string\n): Promise<StoreOrder> {\n const options = await getCheckoutOptions();\n const result = await getClient().store.orders.couponCodes.remove(orderId, promotionId, options);\n revalidateTag('checkout');\n revalidateTag('cart');\n return result;\n}\n\n/**\n * Complete the checkout and place the order.\n */\nexport async function complete(orderId: string): Promise<StoreOrder> {\n const options = await getCheckoutOptions();\n const result = await getClient().store.orders.complete(orderId, options);\n revalidateTag('checkout');\n revalidateTag('cart');\n return result;\n}\n","import { createSpreeClient, type SpreeClient } from '@spree/sdk';\nimport type { SpreeNextConfig } from './types';\n\nlet _client: SpreeClient | null = null;\nlet _config: SpreeNextConfig | null = null;\n\n/**\n * Initialize the Spree Next.js integration.\n * Call this once in your app (e.g., in `lib/storefront.ts`).\n * If not called, the client will auto-initialize from SPREE_API_URL and SPREE_PUBLISHABLE_KEY env vars.\n */\nexport function initSpreeNext(config: SpreeNextConfig): void {\n _config = config;\n _client = createSpreeClient({\n baseUrl: config.baseUrl,\n publishableKey: config.publishableKey,\n });\n}\n\n/**\n * Get the SpreeClient instance. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getClient(): SpreeClient {\n if (!_client) {\n const baseUrl = process.env.SPREE_API_URL;\n const publishableKey = process.env.SPREE_PUBLISHABLE_KEY;\n if (baseUrl && publishableKey) {\n initSpreeNext({ baseUrl, publishableKey });\n } else {\n throw new Error(\n '@spree/next is not configured. Either call initSpreeNext() or set SPREE_API_URL and SPREE_PUBLISHABLE_KEY environment variables.'\n );\n }\n }\n return _client!;\n}\n\n/**\n * Get the current config. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getConfig(): SpreeNextConfig {\n if (!_config) {\n getClient(); // triggers auto-init\n }\n return _config!;\n}\n\n/**\n * Reset the client (useful for testing).\n * @internal\n */\nexport function resetClient(): void {\n _client = null;\n _config = null;\n}\n","import { cookies } from 'next/headers';\nimport { getConfig } from './config';\n\nconst DEFAULT_CART_COOKIE = '_spree_cart_token';\nconst DEFAULT_ACCESS_TOKEN_COOKIE = '_spree_jwt';\nconst CART_TOKEN_MAX_AGE = 60 * 60 * 24 * 30; // 30 days\nconst ACCESS_TOKEN_MAX_AGE = 60 * 60 * 24 * 7; // 7 days\n\nfunction getCartCookieName(): string {\n try {\n return getConfig().cartCookieName ?? DEFAULT_CART_COOKIE;\n } catch {\n return DEFAULT_CART_COOKIE;\n }\n}\n\nfunction getAccessTokenCookieName(): string {\n try {\n return getConfig().accessTokenCookieName ?? DEFAULT_ACCESS_TOKEN_COOKIE;\n } catch {\n return DEFAULT_ACCESS_TOKEN_COOKIE;\n }\n}\n\n// --- Cart Token ---\n\nexport async function getCartToken(): Promise<string | undefined> {\n const cookieStore = await cookies();\n return cookieStore.get(getCartCookieName())?.value;\n}\n\nexport async function setCartToken(token: string): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getCartCookieName(), token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: CART_TOKEN_MAX_AGE,\n });\n}\n\nexport async function clearCartToken(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getCartCookieName(), '', {\n maxAge: -1,\n path: '/',\n });\n}\n\n// --- Access Token (JWT) ---\n\nexport async function getAccessToken(): Promise<string | undefined> {\n const cookieStore = await cookies();\n return cookieStore.get(getAccessTokenCookieName())?.value;\n}\n\nexport async function setAccessToken(token: string): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getAccessTokenCookieName(), token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: ACCESS_TOKEN_MAX_AGE,\n });\n}\n\nexport async function clearAccessToken(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getAccessTokenCookieName(), '', {\n maxAge: -1,\n path: '/',\n });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/actions/checkout.ts","../../src/config.ts","../../src/cookies.ts"],"sourcesContent":["'use server';\n\nimport { revalidateTag } from 'next/cache';\nimport type { Order, Shipment, UpdateOrderParams } from '@spree/sdk';\nimport { getClient } from '../config';\nimport { getCartToken, getAccessToken } from '../cookies';\n\nasync function getCheckoutOptions() {\n const orderToken = await getCartToken();\n const token = await getAccessToken();\n return { orderToken, token };\n}\n\n/**\n * Get the current checkout order state.\n * Includes line_items, shipments, and addresses by default.\n */\nexport async function getCheckout(\n orderId: string\n): Promise<Order> {\n const options = await getCheckoutOptions();\n return getClient().orders.get(\n orderId,\n { expand: ['line_items', 'shipments', 'ship_address', 'bill_address'] },\n options\n );\n}\n\n/**\n * Update an order (addresses, email, currency, locale, metadata, etc.).\n */\nexport async function updateOrder(\n orderId: string,\n params: UpdateOrderParams\n): Promise<Order> {\n const options = await getCheckoutOptions();\n const result = await getClient().orders.update(orderId, params, options);\n revalidateTag('checkout');\n return result;\n}\n\n/**\n * Advance the checkout to the next step.\n */\nexport async function advance(orderId: string): Promise<Order> {\n const options = await getCheckoutOptions();\n const result = await getClient().orders.advance(orderId, options);\n revalidateTag('checkout');\n return result;\n}\n\n/**\n * Move the checkout to the next step (alias for advance).\n */\nexport async function next(orderId: string): Promise<Order> {\n const options = await getCheckoutOptions();\n const result = await getClient().orders.next(orderId, options);\n revalidateTag('checkout');\n return result;\n}\n\n/**\n * Get shipments for the order (includes available shipping rates).\n */\nexport async function getShipments(\n orderId: string\n): Promise<{ data: Shipment[] }> {\n const options = await getCheckoutOptions();\n return getClient().orders.shipments.list(orderId, options);\n}\n\n/**\n * Select a shipping rate for a shipment.\n * Returns the updated order with recalculated totals.\n */\nexport async function selectShippingRate(\n orderId: string,\n shipmentId: string,\n shippingRateId: string\n): Promise<Order> {\n const options = await getCheckoutOptions();\n const result = await getClient().orders.shipments.update(\n orderId,\n shipmentId,\n { selected_shipping_rate_id: shippingRateId },\n options\n );\n revalidateTag('checkout');\n return result;\n}\n\n/**\n * Apply a coupon code to the order.\n */\nexport async function applyCoupon(\n orderId: string,\n code: string\n): Promise<Order> {\n const options = await getCheckoutOptions();\n const result = await getClient().orders.couponCodes.apply(orderId, code, options);\n revalidateTag('checkout');\n revalidateTag('cart');\n return result;\n}\n\n/**\n * Remove a coupon/promotion from the order.\n */\nexport async function removeCoupon(\n orderId: string,\n promotionId: string\n): Promise<Order> {\n const options = await getCheckoutOptions();\n const result = await getClient().orders.couponCodes.remove(orderId, promotionId, options);\n revalidateTag('checkout');\n revalidateTag('cart');\n return result;\n}\n\n/**\n * Complete the checkout and place the order.\n */\nexport async function complete(orderId: string): Promise<Order> {\n const options = await getCheckoutOptions();\n const result = await getClient().orders.complete(orderId, options);\n revalidateTag('checkout');\n revalidateTag('cart');\n return result;\n}\n","import { createClient, type Client } from '@spree/sdk';\nimport type { SpreeNextConfig } from './types';\n\nlet _client: Client | null = null;\nlet _config: SpreeNextConfig | null = null;\n\n/**\n * Initialize the Spree Next.js integration.\n * Call this once in your app (e.g., in `lib/storefront.ts`).\n * If not called, the client will auto-initialize from SPREE_API_URL and SPREE_PUBLISHABLE_KEY env vars.\n */\nexport function initSpreeNext(config: SpreeNextConfig): void {\n _config = config;\n _client = createClient({\n baseUrl: config.baseUrl,\n publishableKey: config.publishableKey,\n });\n}\n\n/**\n * Get the Client instance. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getClient(): Client {\n if (!_client) {\n const baseUrl = process.env.SPREE_API_URL;\n const publishableKey = process.env.SPREE_PUBLISHABLE_KEY;\n if (baseUrl && publishableKey) {\n initSpreeNext({ baseUrl, publishableKey });\n } else {\n throw new Error(\n '@spree/next is not configured. Either call initSpreeNext() or set SPREE_API_URL and SPREE_PUBLISHABLE_KEY environment variables.'\n );\n }\n }\n return _client!;\n}\n\n/**\n * Get the current config. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getConfig(): SpreeNextConfig {\n if (!_config) {\n getClient(); // triggers auto-init\n }\n return _config!;\n}\n\n/**\n * Reset the client (useful for testing).\n * @internal\n */\nexport function resetClient(): void {\n _client = null;\n _config = null;\n}\n","import { cookies } from 'next/headers';\nimport { getConfig } from './config';\n\nconst DEFAULT_CART_COOKIE = '_spree_cart_token';\nconst DEFAULT_ACCESS_TOKEN_COOKIE = '_spree_jwt';\nconst CART_TOKEN_MAX_AGE = 60 * 60 * 24 * 30; // 30 days\nconst ACCESS_TOKEN_MAX_AGE = 60 * 60 * 24 * 7; // 7 days\n\nfunction getCartCookieName(): string {\n try {\n return getConfig().cartCookieName ?? DEFAULT_CART_COOKIE;\n } catch {\n return DEFAULT_CART_COOKIE;\n }\n}\n\nfunction getAccessTokenCookieName(): string {\n try {\n return getConfig().accessTokenCookieName ?? DEFAULT_ACCESS_TOKEN_COOKIE;\n } catch {\n return DEFAULT_ACCESS_TOKEN_COOKIE;\n }\n}\n\n// --- Cart Token ---\n\nexport async function getCartToken(): Promise<string | undefined> {\n const cookieStore = await cookies();\n return cookieStore.get(getCartCookieName())?.value;\n}\n\nexport async function setCartToken(token: string): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getCartCookieName(), token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: CART_TOKEN_MAX_AGE,\n });\n}\n\nexport async function clearCartToken(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getCartCookieName(), '', {\n maxAge: -1,\n path: '/',\n });\n}\n\n// --- Access Token (JWT) ---\n\nexport async function getAccessToken(): Promise<string | undefined> {\n const cookieStore = await cookies();\n return cookieStore.get(getAccessTokenCookieName())?.value;\n}\n\nexport async function setAccessToken(token: string): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getAccessTokenCookieName(), token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: ACCESS_TOKEN_MAX_AGE,\n });\n}\n\nexport async function clearAccessToken(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getAccessTokenCookieName(), '', {\n maxAge: -1,\n path: '/',\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CreditCard } from '@spree/sdk';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* List the authenticated customer's credit cards.
|
|
5
5
|
*/
|
|
6
6
|
declare function listCreditCards(): Promise<{
|
|
7
|
-
data:
|
|
7
|
+
data: CreditCard[];
|
|
8
8
|
}>;
|
|
9
9
|
/**
|
|
10
10
|
* Delete a credit card.
|
|
@@ -7,12 +7,12 @@ import { revalidateTag } from "next/cache";
|
|
|
7
7
|
import { SpreeError } from "@spree/sdk";
|
|
8
8
|
|
|
9
9
|
// src/config.ts
|
|
10
|
-
import {
|
|
10
|
+
import { createClient } from "@spree/sdk";
|
|
11
11
|
var _client = null;
|
|
12
12
|
var _config = null;
|
|
13
13
|
function initSpreeNext(config) {
|
|
14
14
|
_config = config;
|
|
15
|
-
_client =
|
|
15
|
+
_client = createClient({
|
|
16
16
|
baseUrl: config.baseUrl,
|
|
17
17
|
publishableKey: config.publishableKey
|
|
18
18
|
});
|
|
@@ -84,7 +84,7 @@ async function getAuthOptions() {
|
|
|
84
84
|
const now = Math.floor(Date.now() / 1e3);
|
|
85
85
|
if (exp && exp - now < 3600) {
|
|
86
86
|
try {
|
|
87
|
-
const refreshed = await getClient().
|
|
87
|
+
const refreshed = await getClient().auth.refresh({ token });
|
|
88
88
|
await setAccessToken(refreshed.token);
|
|
89
89
|
return { token: refreshed.token };
|
|
90
90
|
} catch {
|
|
@@ -104,7 +104,7 @@ async function withAuthRefresh(fn) {
|
|
|
104
104
|
} catch (error) {
|
|
105
105
|
if (error instanceof SpreeError && error.status === 401) {
|
|
106
106
|
try {
|
|
107
|
-
const refreshed = await getClient().
|
|
107
|
+
const refreshed = await getClient().auth.refresh({ token: options.token });
|
|
108
108
|
await setAccessToken(refreshed.token);
|
|
109
109
|
return await fn({ token: refreshed.token });
|
|
110
110
|
} catch {
|
|
@@ -119,12 +119,12 @@ async function withAuthRefresh(fn) {
|
|
|
119
119
|
// src/actions/credit-cards.ts
|
|
120
120
|
async function listCreditCards() {
|
|
121
121
|
return withAuthRefresh(async (options) => {
|
|
122
|
-
return getClient().
|
|
122
|
+
return getClient().customer.creditCards.list(void 0, options);
|
|
123
123
|
});
|
|
124
124
|
}
|
|
125
125
|
async function deleteCreditCard(id) {
|
|
126
126
|
await withAuthRefresh(async (options) => {
|
|
127
|
-
return getClient().
|
|
127
|
+
return getClient().customer.creditCards.delete(id, options);
|
|
128
128
|
});
|
|
129
129
|
revalidateTag("credit-cards");
|
|
130
130
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/actions/credit-cards.ts","../../src/auth-helpers.ts","../../src/config.ts","../../src/cookies.ts"],"sourcesContent":["'use server';\n\nimport { revalidateTag } from 'next/cache';\nimport type {
|
|
1
|
+
{"version":3,"sources":["../../src/actions/credit-cards.ts","../../src/auth-helpers.ts","../../src/config.ts","../../src/cookies.ts"],"sourcesContent":["'use server';\n\nimport { revalidateTag } from 'next/cache';\nimport type { CreditCard } from '@spree/sdk';\nimport { withAuthRefresh } from '../auth-helpers';\nimport { getClient } from '../config';\n\n/**\n * List the authenticated customer's credit cards.\n */\nexport async function listCreditCards(): Promise<{ data: CreditCard[] }> {\n return withAuthRefresh(async (options) => {\n return getClient().customer.creditCards.list(undefined, options);\n });\n}\n\n/**\n * Delete a credit card.\n */\nexport async function deleteCreditCard(id: string): Promise<void> {\n await withAuthRefresh(async (options) => {\n return getClient().customer.creditCards.delete(id, options);\n });\n revalidateTag('credit-cards');\n}\n","import { SpreeError } from '@spree/sdk';\nimport type { RequestOptions } from '@spree/sdk';\nimport { getClient } from './config';\nimport { getAccessToken, setAccessToken, clearAccessToken } from './cookies';\n\n/**\n * Get auth request options from the current JWT token.\n * Proactively refreshes the token if it expires within 1 hour.\n */\nexport async function getAuthOptions(): Promise<RequestOptions> {\n const token = await getAccessToken();\n if (!token) {\n return {};\n }\n\n // Check if token is close to expiry by decoding JWT payload\n try {\n const payload = JSON.parse(atob(token.split('.')[1]));\n const exp = payload.exp;\n const now = Math.floor(Date.now() / 1000);\n\n // Refresh if token expires in less than 1 hour\n if (exp && exp - now < 3600) {\n try {\n const refreshed = await getClient().auth.refresh({ token });\n await setAccessToken(refreshed.token);\n return { token: refreshed.token };\n } catch {\n // Refresh failed — use existing token, it might still work\n }\n }\n } catch {\n // Can't decode JWT — use it as-is, the server will reject if invalid\n }\n\n return { token };\n}\n\n/**\n * Execute an authenticated request with automatic token refresh on 401.\n * @param fn - Function that takes RequestOptions and returns a promise\n * @returns The result of the function\n * @throws SpreeError if auth fails after refresh attempt\n */\nexport async function withAuthRefresh<T>(\n fn: (options: RequestOptions) => Promise<T>\n): Promise<T> {\n const options = await getAuthOptions();\n\n if (!options.token) {\n throw new Error('Not authenticated');\n }\n\n try {\n return await fn(options);\n } catch (error: unknown) {\n // If 401, try refreshing the token once\n if (error instanceof SpreeError && error.status === 401) {\n try {\n const refreshed = await getClient().auth.refresh({ token: options.token });\n await setAccessToken(refreshed.token);\n return await fn({ token: refreshed.token });\n } catch {\n // Refresh failed — clear token and rethrow\n await clearAccessToken();\n throw error;\n }\n }\n throw error;\n }\n}\n","import { createClient, type Client } from '@spree/sdk';\nimport type { SpreeNextConfig } from './types';\n\nlet _client: Client | null = null;\nlet _config: SpreeNextConfig | null = null;\n\n/**\n * Initialize the Spree Next.js integration.\n * Call this once in your app (e.g., in `lib/storefront.ts`).\n * If not called, the client will auto-initialize from SPREE_API_URL and SPREE_PUBLISHABLE_KEY env vars.\n */\nexport function initSpreeNext(config: SpreeNextConfig): void {\n _config = config;\n _client = createClient({\n baseUrl: config.baseUrl,\n publishableKey: config.publishableKey,\n });\n}\n\n/**\n * Get the Client instance. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getClient(): Client {\n if (!_client) {\n const baseUrl = process.env.SPREE_API_URL;\n const publishableKey = process.env.SPREE_PUBLISHABLE_KEY;\n if (baseUrl && publishableKey) {\n initSpreeNext({ baseUrl, publishableKey });\n } else {\n throw new Error(\n '@spree/next is not configured. Either call initSpreeNext() or set SPREE_API_URL and SPREE_PUBLISHABLE_KEY environment variables.'\n );\n }\n }\n return _client!;\n}\n\n/**\n * Get the current config. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getConfig(): SpreeNextConfig {\n if (!_config) {\n getClient(); // triggers auto-init\n }\n return _config!;\n}\n\n/**\n * Reset the client (useful for testing).\n * @internal\n */\nexport function resetClient(): void {\n _client = null;\n _config = null;\n}\n","import { cookies } from 'next/headers';\nimport { getConfig } from './config';\n\nconst DEFAULT_CART_COOKIE = '_spree_cart_token';\nconst DEFAULT_ACCESS_TOKEN_COOKIE = '_spree_jwt';\nconst CART_TOKEN_MAX_AGE = 60 * 60 * 24 * 30; // 30 days\nconst ACCESS_TOKEN_MAX_AGE = 60 * 60 * 24 * 7; // 7 days\n\nfunction getCartCookieName(): string {\n try {\n return getConfig().cartCookieName ?? DEFAULT_CART_COOKIE;\n } catch {\n return DEFAULT_CART_COOKIE;\n }\n}\n\nfunction getAccessTokenCookieName(): string {\n try {\n return getConfig().accessTokenCookieName ?? DEFAULT_ACCESS_TOKEN_COOKIE;\n } catch {\n return DEFAULT_ACCESS_TOKEN_COOKIE;\n }\n}\n\n// --- Cart Token ---\n\nexport async function getCartToken(): Promise<string | undefined> {\n const cookieStore = await cookies();\n return cookieStore.get(getCartCookieName())?.value;\n}\n\nexport async function setCartToken(token: string): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getCartCookieName(), token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: CART_TOKEN_MAX_AGE,\n });\n}\n\nexport async function clearCartToken(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getCartCookieName(), '', {\n maxAge: -1,\n path: '/',\n });\n}\n\n// --- Access Token (JWT) ---\n\nexport async function getAccessToken(): Promise<string | undefined> {\n const cookieStore = await cookies();\n return cookieStore.get(getAccessTokenCookieName())?.value;\n}\n\nexport async function setAccessToken(token: string): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getAccessTokenCookieName(), token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: ACCESS_TOKEN_MAX_AGE,\n });\n}\n\nexport async function clearAccessToken(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getAccessTokenCookieName(), '', {\n maxAge: -1,\n path: '/',\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GiftCard } from '@spree/sdk';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* List the authenticated customer's gift cards.
|
|
5
5
|
*/
|
|
6
6
|
declare function listGiftCards(): Promise<{
|
|
7
|
-
data:
|
|
7
|
+
data: GiftCard[];
|
|
8
8
|
}>;
|
|
9
9
|
/**
|
|
10
10
|
* Get a single gift card by ID.
|
|
11
11
|
*/
|
|
12
|
-
declare function getGiftCard(id: string): Promise<
|
|
12
|
+
declare function getGiftCard(id: string): Promise<GiftCard>;
|
|
13
13
|
|
|
14
14
|
export { getGiftCard, listGiftCards };
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
import { SpreeError } from "@spree/sdk";
|
|
5
5
|
|
|
6
6
|
// src/config.ts
|
|
7
|
-
import {
|
|
7
|
+
import { createClient } from "@spree/sdk";
|
|
8
8
|
var _client = null;
|
|
9
9
|
var _config = null;
|
|
10
10
|
function initSpreeNext(config) {
|
|
11
11
|
_config = config;
|
|
12
|
-
_client =
|
|
12
|
+
_client = createClient({
|
|
13
13
|
baseUrl: config.baseUrl,
|
|
14
14
|
publishableKey: config.publishableKey
|
|
15
15
|
});
|
|
@@ -81,7 +81,7 @@ async function getAuthOptions() {
|
|
|
81
81
|
const now = Math.floor(Date.now() / 1e3);
|
|
82
82
|
if (exp && exp - now < 3600) {
|
|
83
83
|
try {
|
|
84
|
-
const refreshed = await getClient().
|
|
84
|
+
const refreshed = await getClient().auth.refresh({ token });
|
|
85
85
|
await setAccessToken(refreshed.token);
|
|
86
86
|
return { token: refreshed.token };
|
|
87
87
|
} catch {
|
|
@@ -101,7 +101,7 @@ async function withAuthRefresh(fn) {
|
|
|
101
101
|
} catch (error) {
|
|
102
102
|
if (error instanceof SpreeError && error.status === 401) {
|
|
103
103
|
try {
|
|
104
|
-
const refreshed = await getClient().
|
|
104
|
+
const refreshed = await getClient().auth.refresh({ token: options.token });
|
|
105
105
|
await setAccessToken(refreshed.token);
|
|
106
106
|
return await fn({ token: refreshed.token });
|
|
107
107
|
} catch {
|
|
@@ -116,12 +116,12 @@ async function withAuthRefresh(fn) {
|
|
|
116
116
|
// src/actions/gift-cards.ts
|
|
117
117
|
async function listGiftCards() {
|
|
118
118
|
return withAuthRefresh(async (options) => {
|
|
119
|
-
return getClient().
|
|
119
|
+
return getClient().customer.giftCards.list(void 0, options);
|
|
120
120
|
});
|
|
121
121
|
}
|
|
122
122
|
async function getGiftCard(id) {
|
|
123
123
|
return withAuthRefresh(async (options) => {
|
|
124
|
-
return getClient().
|
|
124
|
+
return getClient().customer.giftCards.get(id, options);
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
127
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/auth-helpers.ts","../../src/config.ts","../../src/cookies.ts","../../src/actions/gift-cards.ts"],"sourcesContent":["import { SpreeError } from '@spree/sdk';\nimport type { RequestOptions } from '@spree/sdk';\nimport { getClient } from './config';\nimport { getAccessToken, setAccessToken, clearAccessToken } from './cookies';\n\n/**\n * Get auth request options from the current JWT token.\n * Proactively refreshes the token if it expires within 1 hour.\n */\nexport async function getAuthOptions(): Promise<RequestOptions> {\n const token = await getAccessToken();\n if (!token) {\n return {};\n }\n\n // Check if token is close to expiry by decoding JWT payload\n try {\n const payload = JSON.parse(atob(token.split('.')[1]));\n const exp = payload.exp;\n const now = Math.floor(Date.now() / 1000);\n\n // Refresh if token expires in less than 1 hour\n if (exp && exp - now < 3600) {\n try {\n const refreshed = await getClient().
|
|
1
|
+
{"version":3,"sources":["../../src/auth-helpers.ts","../../src/config.ts","../../src/cookies.ts","../../src/actions/gift-cards.ts"],"sourcesContent":["import { SpreeError } from '@spree/sdk';\nimport type { RequestOptions } from '@spree/sdk';\nimport { getClient } from './config';\nimport { getAccessToken, setAccessToken, clearAccessToken } from './cookies';\n\n/**\n * Get auth request options from the current JWT token.\n * Proactively refreshes the token if it expires within 1 hour.\n */\nexport async function getAuthOptions(): Promise<RequestOptions> {\n const token = await getAccessToken();\n if (!token) {\n return {};\n }\n\n // Check if token is close to expiry by decoding JWT payload\n try {\n const payload = JSON.parse(atob(token.split('.')[1]));\n const exp = payload.exp;\n const now = Math.floor(Date.now() / 1000);\n\n // Refresh if token expires in less than 1 hour\n if (exp && exp - now < 3600) {\n try {\n const refreshed = await getClient().auth.refresh({ token });\n await setAccessToken(refreshed.token);\n return { token: refreshed.token };\n } catch {\n // Refresh failed — use existing token, it might still work\n }\n }\n } catch {\n // Can't decode JWT — use it as-is, the server will reject if invalid\n }\n\n return { token };\n}\n\n/**\n * Execute an authenticated request with automatic token refresh on 401.\n * @param fn - Function that takes RequestOptions and returns a promise\n * @returns The result of the function\n * @throws SpreeError if auth fails after refresh attempt\n */\nexport async function withAuthRefresh<T>(\n fn: (options: RequestOptions) => Promise<T>\n): Promise<T> {\n const options = await getAuthOptions();\n\n if (!options.token) {\n throw new Error('Not authenticated');\n }\n\n try {\n return await fn(options);\n } catch (error: unknown) {\n // If 401, try refreshing the token once\n if (error instanceof SpreeError && error.status === 401) {\n try {\n const refreshed = await getClient().auth.refresh({ token: options.token });\n await setAccessToken(refreshed.token);\n return await fn({ token: refreshed.token });\n } catch {\n // Refresh failed — clear token and rethrow\n await clearAccessToken();\n throw error;\n }\n }\n throw error;\n }\n}\n","import { createClient, type Client } from '@spree/sdk';\nimport type { SpreeNextConfig } from './types';\n\nlet _client: Client | null = null;\nlet _config: SpreeNextConfig | null = null;\n\n/**\n * Initialize the Spree Next.js integration.\n * Call this once in your app (e.g., in `lib/storefront.ts`).\n * If not called, the client will auto-initialize from SPREE_API_URL and SPREE_PUBLISHABLE_KEY env vars.\n */\nexport function initSpreeNext(config: SpreeNextConfig): void {\n _config = config;\n _client = createClient({\n baseUrl: config.baseUrl,\n publishableKey: config.publishableKey,\n });\n}\n\n/**\n * Get the Client instance. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getClient(): Client {\n if (!_client) {\n const baseUrl = process.env.SPREE_API_URL;\n const publishableKey = process.env.SPREE_PUBLISHABLE_KEY;\n if (baseUrl && publishableKey) {\n initSpreeNext({ baseUrl, publishableKey });\n } else {\n throw new Error(\n '@spree/next is not configured. Either call initSpreeNext() or set SPREE_API_URL and SPREE_PUBLISHABLE_KEY environment variables.'\n );\n }\n }\n return _client!;\n}\n\n/**\n * Get the current config. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getConfig(): SpreeNextConfig {\n if (!_config) {\n getClient(); // triggers auto-init\n }\n return _config!;\n}\n\n/**\n * Reset the client (useful for testing).\n * @internal\n */\nexport function resetClient(): void {\n _client = null;\n _config = null;\n}\n","import { cookies } from 'next/headers';\nimport { getConfig } from './config';\n\nconst DEFAULT_CART_COOKIE = '_spree_cart_token';\nconst DEFAULT_ACCESS_TOKEN_COOKIE = '_spree_jwt';\nconst CART_TOKEN_MAX_AGE = 60 * 60 * 24 * 30; // 30 days\nconst ACCESS_TOKEN_MAX_AGE = 60 * 60 * 24 * 7; // 7 days\n\nfunction getCartCookieName(): string {\n try {\n return getConfig().cartCookieName ?? DEFAULT_CART_COOKIE;\n } catch {\n return DEFAULT_CART_COOKIE;\n }\n}\n\nfunction getAccessTokenCookieName(): string {\n try {\n return getConfig().accessTokenCookieName ?? DEFAULT_ACCESS_TOKEN_COOKIE;\n } catch {\n return DEFAULT_ACCESS_TOKEN_COOKIE;\n }\n}\n\n// --- Cart Token ---\n\nexport async function getCartToken(): Promise<string | undefined> {\n const cookieStore = await cookies();\n return cookieStore.get(getCartCookieName())?.value;\n}\n\nexport async function setCartToken(token: string): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getCartCookieName(), token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: CART_TOKEN_MAX_AGE,\n });\n}\n\nexport async function clearCartToken(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getCartCookieName(), '', {\n maxAge: -1,\n path: '/',\n });\n}\n\n// --- Access Token (JWT) ---\n\nexport async function getAccessToken(): Promise<string | undefined> {\n const cookieStore = await cookies();\n return cookieStore.get(getAccessTokenCookieName())?.value;\n}\n\nexport async function setAccessToken(token: string): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getAccessTokenCookieName(), token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: ACCESS_TOKEN_MAX_AGE,\n });\n}\n\nexport async function clearAccessToken(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getAccessTokenCookieName(), '', {\n maxAge: -1,\n path: '/',\n });\n}\n","'use server';\n\nimport type { GiftCard } from '@spree/sdk';\nimport { withAuthRefresh } from '../auth-helpers';\nimport { getClient } from '../config';\n\n/**\n * List the authenticated customer's gift cards.\n */\nexport async function listGiftCards(): Promise<{ data: GiftCard[] }> {\n return withAuthRefresh(async (options) => {\n return getClient().customer.giftCards.list(undefined, options);\n });\n}\n\n/**\n * Get a single gift card by ID.\n */\nexport async function getGiftCard(id: string): Promise<GiftCard> {\n return withAuthRefresh(async (options) => {\n return getClient().customer.giftCards.get(id, options);\n });\n}\n"],"mappings":";;;AAAA,SAAS,kBAAkB;;;ACA3B,SAAS,oBAAiC;AAG1C,IAAI,UAAyB;AAC7B,IAAI,UAAkC;AAO/B,SAAS,cAAc,QAA+B;AAC3D,YAAU;AACV,YAAU,aAAa;AAAA,IACrB,SAAS,OAAO;AAAA,IAChB,gBAAgB,OAAO;AAAA,EACzB,CAAC;AACH;AAMO,SAAS,YAAoB;AAClC,MAAI,CAAC,SAAS;AACZ,UAAM,UAAU,QAAQ,IAAI;AAC5B,UAAM,iBAAiB,QAAQ,IAAI;AACnC,QAAI,WAAW,gBAAgB;AAC7B,oBAAc,EAAE,SAAS,eAAe,CAAC;AAAA,IAC3C,OAAO;AACL,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,YAA6B;AAC3C,MAAI,CAAC,SAAS;AACZ,cAAU;AAAA,EACZ;AACA,SAAO;AACT;;;AC/CA,SAAS,eAAe;AAIxB,IAAM,8BAA8B;AACpC,IAAM,qBAAqB,KAAK,KAAK,KAAK;AAC1C,IAAM,uBAAuB,KAAK,KAAK,KAAK;AAU5C,SAAS,2BAAmC;AAC1C,MAAI;AACF,WAAO,UAAU,EAAE,yBAAyB;AAAA,EAC9C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AA8BA,eAAsB,iBAA8C;AAClE,QAAM,cAAc,MAAM,QAAQ;AAClC,SAAO,YAAY,IAAI,yBAAyB,CAAC,GAAG;AACtD;AAEA,eAAsB,eAAe,OAA8B;AACjE,QAAM,cAAc,MAAM,QAAQ;AAClC,cAAY,IAAI,yBAAyB,GAAG,OAAO;AAAA,IACjD,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,UAAU;AAAA,IACV,MAAM;AAAA,IACN,QAAQ;AAAA,EACV,CAAC;AACH;AAEA,eAAsB,mBAAkC;AACtD,QAAM,cAAc,MAAM,QAAQ;AAClC,cAAY,IAAI,yBAAyB,GAAG,IAAI;AAAA,IAC9C,QAAQ;AAAA,IACR,MAAM;AAAA,EACR,CAAC;AACH;;;AFjEA,eAAsB,iBAA0C;AAC9D,QAAM,QAAQ,MAAM,eAAe;AACnC,MAAI,CAAC,OAAO;AACV,WAAO,CAAC;AAAA,EACV;AAGA,MAAI;AACF,UAAM,UAAU,KAAK,MAAM,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC;AACpD,UAAM,MAAM,QAAQ;AACpB,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAGxC,QAAI,OAAO,MAAM,MAAM,MAAM;AAC3B,UAAI;AACF,cAAM,YAAY,MAAM,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,CAAC;AAC1D,cAAM,eAAe,UAAU,KAAK;AACpC,eAAO,EAAE,OAAO,UAAU,MAAM;AAAA,MAClC,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO,EAAE,MAAM;AACjB;AAQA,eAAsB,gBACpB,IACY;AACZ,QAAM,UAAU,MAAM,eAAe;AAErC,MAAI,CAAC,QAAQ,OAAO;AAClB,UAAM,IAAI,MAAM,mBAAmB;AAAA,EACrC;AAEA,MAAI;AACF,WAAO,MAAM,GAAG,OAAO;AAAA,EACzB,SAAS,OAAgB;AAEvB,QAAI,iBAAiB,cAAc,MAAM,WAAW,KAAK;AACvD,UAAI;AACF,cAAM,YAAY,MAAM,UAAU,EAAE,KAAK,QAAQ,EAAE,OAAO,QAAQ,MAAM,CAAC;AACzE,cAAM,eAAe,UAAU,KAAK;AACpC,eAAO,MAAM,GAAG,EAAE,OAAO,UAAU,MAAM,CAAC;AAAA,MAC5C,QAAQ;AAEN,cAAM,iBAAiB;AACvB,cAAM;AAAA,MACR;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;;;AG7DA,eAAsB,gBAA+C;AACnE,SAAO,gBAAgB,OAAO,YAAY;AACxC,WAAO,UAAU,EAAE,SAAS,UAAU,KAAK,QAAW,OAAO;AAAA,EAC/D,CAAC;AACH;AAKA,eAAsB,YAAY,IAA+B;AAC/D,SAAO,gBAAgB,OAAO,YAAY;AACxC,WAAO,UAAU,EAAE,SAAS,UAAU,IAAI,IAAI,OAAO;AAAA,EACvD,CAAC;AACH;","names":[]}
|
package/dist/actions/locale.js
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
import { cookies } from "next/headers";
|
|
5
5
|
|
|
6
6
|
// src/config.ts
|
|
7
|
-
import {
|
|
7
|
+
import { createClient } from "@spree/sdk";
|
|
8
8
|
var _client = null;
|
|
9
9
|
var _config = null;
|
|
10
10
|
function initSpreeNext(config) {
|
|
11
11
|
_config = config;
|
|
12
|
-
_client =
|
|
12
|
+
_client = createClient({
|
|
13
13
|
baseUrl: config.baseUrl,
|
|
14
14
|
publishableKey: config.publishableKey
|
|
15
15
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/actions/locale.ts","../../src/config.ts"],"sourcesContent":["'use server';\n\nimport { cookies } from 'next/headers';\nimport { getConfig } from '../config';\n\n/**\n * Set locale/country cookies for subsequent requests.\n * Use this in country/language switchers instead of manipulating cookies directly.\n */\nexport async function setLocale(params: {\n country?: string;\n locale?: string;\n}): Promise<void> {\n const config = getConfig();\n const cookieStore = await cookies();\n const maxAge = 60 * 60 * 24 * 365; // 1 year\n\n if (params.country) {\n cookieStore.set(config.countryCookieName ?? 'spree_country', params.country, {\n path: '/',\n maxAge,\n });\n }\n if (params.locale) {\n cookieStore.set(config.localeCookieName ?? 'spree_locale', params.locale, {\n path: '/',\n maxAge,\n });\n }\n}\n","import {
|
|
1
|
+
{"version":3,"sources":["../../src/actions/locale.ts","../../src/config.ts"],"sourcesContent":["'use server';\n\nimport { cookies } from 'next/headers';\nimport { getConfig } from '../config';\n\n/**\n * Set locale/country cookies for subsequent requests.\n * Use this in country/language switchers instead of manipulating cookies directly.\n */\nexport async function setLocale(params: {\n country?: string;\n locale?: string;\n}): Promise<void> {\n const config = getConfig();\n const cookieStore = await cookies();\n const maxAge = 60 * 60 * 24 * 365; // 1 year\n\n if (params.country) {\n cookieStore.set(config.countryCookieName ?? 'spree_country', params.country, {\n path: '/',\n maxAge,\n });\n }\n if (params.locale) {\n cookieStore.set(config.localeCookieName ?? 'spree_locale', params.locale, {\n path: '/',\n maxAge,\n });\n }\n}\n","import { createClient, type Client } from '@spree/sdk';\nimport type { SpreeNextConfig } from './types';\n\nlet _client: Client | null = null;\nlet _config: SpreeNextConfig | null = null;\n\n/**\n * Initialize the Spree Next.js integration.\n * Call this once in your app (e.g., in `lib/storefront.ts`).\n * If not called, the client will auto-initialize from SPREE_API_URL and SPREE_PUBLISHABLE_KEY env vars.\n */\nexport function initSpreeNext(config: SpreeNextConfig): void {\n _config = config;\n _client = createClient({\n baseUrl: config.baseUrl,\n publishableKey: config.publishableKey,\n });\n}\n\n/**\n * Get the Client instance. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getClient(): Client {\n if (!_client) {\n const baseUrl = process.env.SPREE_API_URL;\n const publishableKey = process.env.SPREE_PUBLISHABLE_KEY;\n if (baseUrl && publishableKey) {\n initSpreeNext({ baseUrl, publishableKey });\n } else {\n throw new Error(\n '@spree/next is not configured. Either call initSpreeNext() or set SPREE_API_URL and SPREE_PUBLISHABLE_KEY environment variables.'\n );\n }\n }\n return _client!;\n}\n\n/**\n * Get the current config. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getConfig(): SpreeNextConfig {\n if (!_config) {\n getClient(); // triggers auto-init\n }\n return _config!;\n}\n\n/**\n * Reset the client (useful for testing).\n * @internal\n */\nexport function resetClient(): void {\n _client = null;\n _config = null;\n}\n"],"mappings":";;;AAEA,SAAS,eAAe;;;ACFxB,SAAS,oBAAiC;AAG1C,IAAI,UAAyB;AAC7B,IAAI,UAAkC;AAO/B,SAAS,cAAc,QAA+B;AAC3D,YAAU;AACV,YAAU,aAAa;AAAA,IACrB,SAAS,OAAO;AAAA,IAChB,gBAAgB,OAAO;AAAA,EACzB,CAAC;AACH;AAMO,SAAS,YAAoB;AAClC,MAAI,CAAC,SAAS;AACZ,UAAM,UAAU,QAAQ,IAAI;AAC5B,UAAM,iBAAiB,QAAQ,IAAI;AACnC,QAAI,WAAW,gBAAgB;AAC7B,oBAAc,EAAE,SAAS,eAAe,CAAC;AAAA,IAC3C,OAAO;AACL,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,YAA6B;AAC3C,MAAI,CAAC,SAAS;AACZ,cAAU;AAAA,EACZ;AACA,SAAO;AACT;;;ADtCA,eAAsB,UAAU,QAGd;AAChB,QAAM,SAAS,UAAU;AACzB,QAAM,cAAc,MAAM,QAAQ;AAClC,QAAM,SAAS,KAAK,KAAK,KAAK;AAE9B,MAAI,OAAO,SAAS;AAClB,gBAAY,IAAI,OAAO,qBAAqB,iBAAiB,OAAO,SAAS;AAAA,MAC3E,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH;AACA,MAAI,OAAO,QAAQ;AACjB,gBAAY,IAAI,OAAO,oBAAoB,gBAAgB,OAAO,QAAQ;AAAA,MACxE,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH;AACF;","names":[]}
|
package/dist/actions/orders.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Order, OrderListParams, PaginatedResponse } from '@spree/sdk';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* List the authenticated customer's orders.
|
|
5
5
|
*/
|
|
6
|
-
declare function listOrders(params?: OrderListParams): Promise<PaginatedResponse<
|
|
6
|
+
declare function listOrders(params?: OrderListParams): Promise<PaginatedResponse<Order>>;
|
|
7
7
|
/**
|
|
8
8
|
* Get a single order by ID or number.
|
|
9
9
|
*/
|
|
10
|
-
declare function getOrder(idOrNumber: string, params?: Record<string, unknown>): Promise<
|
|
10
|
+
declare function getOrder(idOrNumber: string, params?: Record<string, unknown>): Promise<Order>;
|
|
11
11
|
|
|
12
12
|
export { getOrder, listOrders };
|
package/dist/actions/orders.js
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
import { SpreeError } from "@spree/sdk";
|
|
5
5
|
|
|
6
6
|
// src/config.ts
|
|
7
|
-
import {
|
|
7
|
+
import { createClient } from "@spree/sdk";
|
|
8
8
|
var _client = null;
|
|
9
9
|
var _config = null;
|
|
10
10
|
function initSpreeNext(config) {
|
|
11
11
|
_config = config;
|
|
12
|
-
_client =
|
|
12
|
+
_client = createClient({
|
|
13
13
|
baseUrl: config.baseUrl,
|
|
14
14
|
publishableKey: config.publishableKey
|
|
15
15
|
});
|
|
@@ -81,7 +81,7 @@ async function getAuthOptions() {
|
|
|
81
81
|
const now = Math.floor(Date.now() / 1e3);
|
|
82
82
|
if (exp && exp - now < 3600) {
|
|
83
83
|
try {
|
|
84
|
-
const refreshed = await getClient().
|
|
84
|
+
const refreshed = await getClient().auth.refresh({ token });
|
|
85
85
|
await setAccessToken(refreshed.token);
|
|
86
86
|
return { token: refreshed.token };
|
|
87
87
|
} catch {
|
|
@@ -101,7 +101,7 @@ async function withAuthRefresh(fn) {
|
|
|
101
101
|
} catch (error) {
|
|
102
102
|
if (error instanceof SpreeError && error.status === 401) {
|
|
103
103
|
try {
|
|
104
|
-
const refreshed = await getClient().
|
|
104
|
+
const refreshed = await getClient().auth.refresh({ token: options.token });
|
|
105
105
|
await setAccessToken(refreshed.token);
|
|
106
106
|
return await fn({ token: refreshed.token });
|
|
107
107
|
} catch {
|
|
@@ -116,12 +116,12 @@ async function withAuthRefresh(fn) {
|
|
|
116
116
|
// src/actions/orders.ts
|
|
117
117
|
async function listOrders(params) {
|
|
118
118
|
return withAuthRefresh(async (options) => {
|
|
119
|
-
return getClient().
|
|
119
|
+
return getClient().customer.orders.list(params, options);
|
|
120
120
|
});
|
|
121
121
|
}
|
|
122
122
|
async function getOrder(idOrNumber, params) {
|
|
123
123
|
return withAuthRefresh(async (options) => {
|
|
124
|
-
return getClient().
|
|
124
|
+
return getClient().orders.get(idOrNumber, params, options);
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
127
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/auth-helpers.ts","../../src/config.ts","../../src/cookies.ts","../../src/actions/orders.ts"],"sourcesContent":["import { SpreeError } from '@spree/sdk';\nimport type { RequestOptions } from '@spree/sdk';\nimport { getClient } from './config';\nimport { getAccessToken, setAccessToken, clearAccessToken } from './cookies';\n\n/**\n * Get auth request options from the current JWT token.\n * Proactively refreshes the token if it expires within 1 hour.\n */\nexport async function getAuthOptions(): Promise<RequestOptions> {\n const token = await getAccessToken();\n if (!token) {\n return {};\n }\n\n // Check if token is close to expiry by decoding JWT payload\n try {\n const payload = JSON.parse(atob(token.split('.')[1]));\n const exp = payload.exp;\n const now = Math.floor(Date.now() / 1000);\n\n // Refresh if token expires in less than 1 hour\n if (exp && exp - now < 3600) {\n try {\n const refreshed = await getClient().
|
|
1
|
+
{"version":3,"sources":["../../src/auth-helpers.ts","../../src/config.ts","../../src/cookies.ts","../../src/actions/orders.ts"],"sourcesContent":["import { SpreeError } from '@spree/sdk';\nimport type { RequestOptions } from '@spree/sdk';\nimport { getClient } from './config';\nimport { getAccessToken, setAccessToken, clearAccessToken } from './cookies';\n\n/**\n * Get auth request options from the current JWT token.\n * Proactively refreshes the token if it expires within 1 hour.\n */\nexport async function getAuthOptions(): Promise<RequestOptions> {\n const token = await getAccessToken();\n if (!token) {\n return {};\n }\n\n // Check if token is close to expiry by decoding JWT payload\n try {\n const payload = JSON.parse(atob(token.split('.')[1]));\n const exp = payload.exp;\n const now = Math.floor(Date.now() / 1000);\n\n // Refresh if token expires in less than 1 hour\n if (exp && exp - now < 3600) {\n try {\n const refreshed = await getClient().auth.refresh({ token });\n await setAccessToken(refreshed.token);\n return { token: refreshed.token };\n } catch {\n // Refresh failed — use existing token, it might still work\n }\n }\n } catch {\n // Can't decode JWT — use it as-is, the server will reject if invalid\n }\n\n return { token };\n}\n\n/**\n * Execute an authenticated request with automatic token refresh on 401.\n * @param fn - Function that takes RequestOptions and returns a promise\n * @returns The result of the function\n * @throws SpreeError if auth fails after refresh attempt\n */\nexport async function withAuthRefresh<T>(\n fn: (options: RequestOptions) => Promise<T>\n): Promise<T> {\n const options = await getAuthOptions();\n\n if (!options.token) {\n throw new Error('Not authenticated');\n }\n\n try {\n return await fn(options);\n } catch (error: unknown) {\n // If 401, try refreshing the token once\n if (error instanceof SpreeError && error.status === 401) {\n try {\n const refreshed = await getClient().auth.refresh({ token: options.token });\n await setAccessToken(refreshed.token);\n return await fn({ token: refreshed.token });\n } catch {\n // Refresh failed — clear token and rethrow\n await clearAccessToken();\n throw error;\n }\n }\n throw error;\n }\n}\n","import { createClient, type Client } from '@spree/sdk';\nimport type { SpreeNextConfig } from './types';\n\nlet _client: Client | null = null;\nlet _config: SpreeNextConfig | null = null;\n\n/**\n * Initialize the Spree Next.js integration.\n * Call this once in your app (e.g., in `lib/storefront.ts`).\n * If not called, the client will auto-initialize from SPREE_API_URL and SPREE_PUBLISHABLE_KEY env vars.\n */\nexport function initSpreeNext(config: SpreeNextConfig): void {\n _config = config;\n _client = createClient({\n baseUrl: config.baseUrl,\n publishableKey: config.publishableKey,\n });\n}\n\n/**\n * Get the Client instance. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getClient(): Client {\n if (!_client) {\n const baseUrl = process.env.SPREE_API_URL;\n const publishableKey = process.env.SPREE_PUBLISHABLE_KEY;\n if (baseUrl && publishableKey) {\n initSpreeNext({ baseUrl, publishableKey });\n } else {\n throw new Error(\n '@spree/next is not configured. Either call initSpreeNext() or set SPREE_API_URL and SPREE_PUBLISHABLE_KEY environment variables.'\n );\n }\n }\n return _client!;\n}\n\n/**\n * Get the current config. Auto-initializes from env vars if needed.\n * @internal\n */\nexport function getConfig(): SpreeNextConfig {\n if (!_config) {\n getClient(); // triggers auto-init\n }\n return _config!;\n}\n\n/**\n * Reset the client (useful for testing).\n * @internal\n */\nexport function resetClient(): void {\n _client = null;\n _config = null;\n}\n","import { cookies } from 'next/headers';\nimport { getConfig } from './config';\n\nconst DEFAULT_CART_COOKIE = '_spree_cart_token';\nconst DEFAULT_ACCESS_TOKEN_COOKIE = '_spree_jwt';\nconst CART_TOKEN_MAX_AGE = 60 * 60 * 24 * 30; // 30 days\nconst ACCESS_TOKEN_MAX_AGE = 60 * 60 * 24 * 7; // 7 days\n\nfunction getCartCookieName(): string {\n try {\n return getConfig().cartCookieName ?? DEFAULT_CART_COOKIE;\n } catch {\n return DEFAULT_CART_COOKIE;\n }\n}\n\nfunction getAccessTokenCookieName(): string {\n try {\n return getConfig().accessTokenCookieName ?? DEFAULT_ACCESS_TOKEN_COOKIE;\n } catch {\n return DEFAULT_ACCESS_TOKEN_COOKIE;\n }\n}\n\n// --- Cart Token ---\n\nexport async function getCartToken(): Promise<string | undefined> {\n const cookieStore = await cookies();\n return cookieStore.get(getCartCookieName())?.value;\n}\n\nexport async function setCartToken(token: string): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getCartCookieName(), token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: CART_TOKEN_MAX_AGE,\n });\n}\n\nexport async function clearCartToken(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getCartCookieName(), '', {\n maxAge: -1,\n path: '/',\n });\n}\n\n// --- Access Token (JWT) ---\n\nexport async function getAccessToken(): Promise<string | undefined> {\n const cookieStore = await cookies();\n return cookieStore.get(getAccessTokenCookieName())?.value;\n}\n\nexport async function setAccessToken(token: string): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getAccessTokenCookieName(), token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: ACCESS_TOKEN_MAX_AGE,\n });\n}\n\nexport async function clearAccessToken(): Promise<void> {\n const cookieStore = await cookies();\n cookieStore.set(getAccessTokenCookieName(), '', {\n maxAge: -1,\n path: '/',\n });\n}\n","'use server';\n\nimport type { Order, PaginatedResponse, OrderListParams } from '@spree/sdk';\nimport { withAuthRefresh } from '../auth-helpers';\nimport { getClient } from '../config';\n\n/**\n * List the authenticated customer's orders.\n */\nexport async function listOrders(\n params?: OrderListParams\n): Promise<PaginatedResponse<Order>> {\n return withAuthRefresh(async (options) => {\n return getClient().customer.orders.list(params, options);\n });\n}\n\n/**\n * Get a single order by ID or number.\n */\nexport async function getOrder(\n idOrNumber: string,\n params?: Record<string, unknown>\n): Promise<Order> {\n return withAuthRefresh(async (options) => {\n return getClient().orders.get(idOrNumber, params, options);\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { CompletePaymentSessionParams,
|
|
1
|
+
import { CompletePaymentSessionParams, PaymentSession, CreatePaymentSessionParams, UpdatePaymentSessionParams } from '@spree/sdk';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Create a payment session for an order.
|
|
5
5
|
* Delegates to the payment gateway to initialize a provider-specific session.
|
|
6
6
|
*/
|
|
7
|
-
declare function createPaymentSession(orderId: string, params: CreatePaymentSessionParams): Promise<
|
|
7
|
+
declare function createPaymentSession(orderId: string, params: CreatePaymentSessionParams): Promise<PaymentSession>;
|
|
8
8
|
/**
|
|
9
9
|
* Get a payment session by ID.
|
|
10
10
|
*/
|
|
11
|
-
declare function getPaymentSession(orderId: string, sessionId: string): Promise<
|
|
11
|
+
declare function getPaymentSession(orderId: string, sessionId: string): Promise<PaymentSession>;
|
|
12
12
|
/**
|
|
13
13
|
* Update a payment session.
|
|
14
14
|
* Delegates to the payment gateway to sync changes with the provider.
|
|
15
15
|
*/
|
|
16
|
-
declare function updatePaymentSession(orderId: string, sessionId: string, params: UpdatePaymentSessionParams): Promise<
|
|
16
|
+
declare function updatePaymentSession(orderId: string, sessionId: string, params: UpdatePaymentSessionParams): Promise<PaymentSession>;
|
|
17
17
|
/**
|
|
18
18
|
* Complete a payment session.
|
|
19
19
|
* Confirms the payment with the provider, triggering capture/authorization.
|
|
20
20
|
*/
|
|
21
|
-
declare function completePaymentSession(orderId: string, sessionId: string, params?: CompletePaymentSessionParams): Promise<
|
|
21
|
+
declare function completePaymentSession(orderId: string, sessionId: string, params?: CompletePaymentSessionParams): Promise<PaymentSession>;
|
|
22
22
|
|
|
23
23
|
export { completePaymentSession, createPaymentSession, getPaymentSession, updatePaymentSession };
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
import { revalidateTag } from "next/cache";
|
|
5
5
|
|
|
6
6
|
// src/config.ts
|
|
7
|
-
import {
|
|
7
|
+
import { createClient } from "@spree/sdk";
|
|
8
8
|
var _client = null;
|
|
9
9
|
var _config = null;
|
|
10
10
|
function initSpreeNext(config) {
|
|
11
11
|
_config = config;
|
|
12
|
-
_client =
|
|
12
|
+
_client = createClient({
|
|
13
13
|
baseUrl: config.baseUrl,
|
|
14
14
|
publishableKey: config.publishableKey
|
|
15
15
|
});
|
|
@@ -72,23 +72,23 @@ async function getCheckoutOptions() {
|
|
|
72
72
|
}
|
|
73
73
|
async function createPaymentSession(orderId, params) {
|
|
74
74
|
const options = await getCheckoutOptions();
|
|
75
|
-
const result = await getClient().
|
|
75
|
+
const result = await getClient().orders.paymentSessions.create(orderId, params, options);
|
|
76
76
|
revalidateTag("checkout");
|
|
77
77
|
return result;
|
|
78
78
|
}
|
|
79
79
|
async function getPaymentSession(orderId, sessionId) {
|
|
80
80
|
const options = await getCheckoutOptions();
|
|
81
|
-
return getClient().
|
|
81
|
+
return getClient().orders.paymentSessions.get(orderId, sessionId, options);
|
|
82
82
|
}
|
|
83
83
|
async function updatePaymentSession(orderId, sessionId, params) {
|
|
84
84
|
const options = await getCheckoutOptions();
|
|
85
|
-
const result = await getClient().
|
|
85
|
+
const result = await getClient().orders.paymentSessions.update(orderId, sessionId, params, options);
|
|
86
86
|
revalidateTag("checkout");
|
|
87
87
|
return result;
|
|
88
88
|
}
|
|
89
89
|
async function completePaymentSession(orderId, sessionId, params) {
|
|
90
90
|
const options = await getCheckoutOptions();
|
|
91
|
-
const result = await getClient().
|
|
91
|
+
const result = await getClient().orders.paymentSessions.complete(orderId, sessionId, params, options);
|
|
92
92
|
revalidateTag("checkout");
|
|
93
93
|
return result;
|
|
94
94
|
}
|