@tagadapay/plugin-sdk 2.3.3 → 2.3.5

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.
@@ -0,0 +1,47 @@
1
+ export interface Discount {
2
+ id: string;
3
+ promotionId: string;
4
+ promotionCodeId: string | null;
5
+ appliedAt: string;
6
+ appliedManually: boolean;
7
+ promotion: {
8
+ id: string;
9
+ name: string;
10
+ };
11
+ }
12
+ export interface DiscountCodeValidation {
13
+ isValid: boolean;
14
+ code: string;
15
+ error?: string;
16
+ discount?: {
17
+ id: string;
18
+ name: string;
19
+ type: string;
20
+ value: number;
21
+ currency: string;
22
+ };
23
+ }
24
+ export interface UseDiscountsOptions {
25
+ checkoutSessionId?: string;
26
+ autoRefresh?: boolean;
27
+ }
28
+ export interface UseDiscountsResult {
29
+ appliedDiscounts: Discount[];
30
+ isLoading: boolean;
31
+ isApplying: boolean;
32
+ isRemoving: boolean;
33
+ error: Error | null;
34
+ applyDiscountCode: (code: string) => Promise<{
35
+ success: boolean;
36
+ error?: string;
37
+ discount?: Discount;
38
+ }>;
39
+ removeDiscountCode: (discountId: string) => Promise<{
40
+ success: boolean;
41
+ error?: string;
42
+ }>;
43
+ getAppliedDiscounts: () => Promise<Discount[]>;
44
+ refresh: () => Promise<void>;
45
+ clearError: () => void;
46
+ }
47
+ export declare function useDiscounts(options?: UseDiscountsOptions): UseDiscountsResult;
@@ -0,0 +1,163 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { useTagadaContext } from '../providers/TagadaProvider';
3
+ export function useDiscounts(options = {}) {
4
+ const { apiService, refreshCoordinator } = useTagadaContext();
5
+ const { checkoutSessionId, autoRefresh = true } = options;
6
+ const [appliedDiscounts, setAppliedDiscounts] = useState([]);
7
+ const [isLoading, setIsLoading] = useState(false);
8
+ const [isApplying, setIsApplying] = useState(false);
9
+ const [isRemoving, setIsRemoving] = useState(false);
10
+ const [error, setError] = useState(null);
11
+ const clearError = useCallback(() => {
12
+ setError(null);
13
+ }, []);
14
+ const getAppliedDiscounts = useCallback(async () => {
15
+ if (!checkoutSessionId) {
16
+ throw new Error('No checkout session available');
17
+ }
18
+ setIsLoading(true);
19
+ setError(null);
20
+ try {
21
+ const response = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/promotions`, {
22
+ method: 'GET',
23
+ });
24
+ setAppliedDiscounts(response);
25
+ return response;
26
+ }
27
+ catch (err) {
28
+ const error = err instanceof Error ? err : new Error('Failed to fetch applied discounts');
29
+ setError(error);
30
+ console.error('Failed to fetch applied discounts:', error);
31
+ throw error;
32
+ }
33
+ finally {
34
+ setIsLoading(false);
35
+ }
36
+ }, [checkoutSessionId, apiService]);
37
+ const applyDiscountCode = useCallback(async (code) => {
38
+ if (!checkoutSessionId) {
39
+ return { success: false, error: 'No checkout session available' };
40
+ }
41
+ if (!code || code.trim() === '') {
42
+ return { success: false, error: 'Discount code is required' };
43
+ }
44
+ setIsApplying(true);
45
+ setError(null);
46
+ try {
47
+ const response = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/promotions/apply`, {
48
+ method: 'POST',
49
+ body: { code: code.trim() },
50
+ });
51
+ if (response.success) {
52
+ // Refresh the applied discounts list
53
+ await getAppliedDiscounts();
54
+ // Trigger a refresh of the checkout session
55
+ refreshCoordinator?.notifyCheckoutChanged();
56
+ return { success: true, discount: response.promotion };
57
+ }
58
+ else {
59
+ return { success: false, error: response.error?.message || 'Failed to apply discount code' };
60
+ }
61
+ }
62
+ catch (err) {
63
+ const error = err instanceof Error ? err : new Error('Failed to apply discount code');
64
+ setError(error);
65
+ console.error('Failed to apply discount code:', error);
66
+ // Try to extract error message from API response
67
+ let errorMessage = 'Failed to apply discount code';
68
+ if (err && typeof err === 'object' && 'response' in err) {
69
+ const apiError = err;
70
+ if (apiError.response?.data?.error?.message) {
71
+ errorMessage = apiError.response.data.error.message;
72
+ }
73
+ else if (apiError.response?.data?.message) {
74
+ errorMessage = apiError.response.data.message;
75
+ }
76
+ }
77
+ return { success: false, error: errorMessage };
78
+ }
79
+ finally {
80
+ setIsApplying(false);
81
+ }
82
+ }, [checkoutSessionId, apiService, getAppliedDiscounts, refreshCoordinator]);
83
+ const removeDiscountCode = useCallback(async (discountId) => {
84
+ if (!checkoutSessionId) {
85
+ return { success: false, error: 'No checkout session available' };
86
+ }
87
+ if (!discountId) {
88
+ return { success: false, error: 'Discount ID is required' };
89
+ }
90
+ setIsRemoving(true);
91
+ setError(null);
92
+ try {
93
+ const response = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/promotions/${discountId}`, {
94
+ method: 'DELETE',
95
+ });
96
+ if (response.success) {
97
+ // Refresh the applied discounts list
98
+ await getAppliedDiscounts();
99
+ // Trigger a refresh of the checkout session
100
+ refreshCoordinator?.notifyCheckoutChanged();
101
+ return { success: true };
102
+ }
103
+ else {
104
+ return { success: false, error: response.error?.message || 'Failed to remove discount' };
105
+ }
106
+ }
107
+ catch (err) {
108
+ const error = err instanceof Error ? err : new Error('Failed to remove discount');
109
+ setError(error);
110
+ console.error('Failed to remove discount:', error);
111
+ // Try to extract error message from API response
112
+ let errorMessage = 'Failed to remove discount';
113
+ if (err && typeof err === 'object' && 'response' in err) {
114
+ const apiError = err;
115
+ if (apiError.response?.data?.error?.message) {
116
+ errorMessage = apiError.response.data.error.message;
117
+ }
118
+ else if (apiError.response?.data?.message) {
119
+ errorMessage = apiError.response.data.message;
120
+ }
121
+ }
122
+ return { success: false, error: errorMessage };
123
+ }
124
+ finally {
125
+ setIsRemoving(false);
126
+ }
127
+ }, [checkoutSessionId, apiService, getAppliedDiscounts, refreshCoordinator]);
128
+ const refresh = useCallback(async () => {
129
+ if (checkoutSessionId) {
130
+ await getAppliedDiscounts();
131
+ }
132
+ }, [checkoutSessionId, getAppliedDiscounts]);
133
+ // Auto-refresh when checkout session changes
134
+ useEffect(() => {
135
+ if (autoRefresh && checkoutSessionId) {
136
+ getAppliedDiscounts();
137
+ }
138
+ }, [checkoutSessionId, autoRefresh, getAppliedDiscounts]);
139
+ // Listen for checkout session refreshes
140
+ useEffect(() => {
141
+ if (!autoRefresh || !checkoutSessionId)
142
+ return;
143
+ const handleRefresh = async () => {
144
+ await getAppliedDiscounts();
145
+ };
146
+ refreshCoordinator?.registerCheckoutRefresh(handleRefresh);
147
+ return () => refreshCoordinator?.unregisterCheckoutRefresh();
148
+ }, [checkoutSessionId, autoRefresh, getAppliedDiscounts, refreshCoordinator]);
149
+ return {
150
+ // State
151
+ appliedDiscounts,
152
+ isLoading,
153
+ isApplying,
154
+ isRemoving,
155
+ error,
156
+ // Actions
157
+ applyDiscountCode,
158
+ removeDiscountCode,
159
+ getAppliedDiscounts,
160
+ refresh,
161
+ clearError,
162
+ };
163
+ }
@@ -151,12 +151,15 @@ export function usePayment() {
151
151
  },
152
152
  });
153
153
  // Create payment instrument through API
154
+ const { expiration_month, expiration_year } = getCardMonthAndYear(cardData.expiryDate);
154
155
  const paymentInstrumentData = {
155
156
  type: btResponse.type,
156
157
  card: {
157
- maskedCardNumber: String(btResponse?.data?.number || ''),
158
- expirationMonth: Number(btResponse?.data?.expiration_month || 0),
159
- expirationYear: Number(btResponse?.data?.expiration_year || 0),
158
+ maskedCardNumber: btResponse.enrichments?.cardDetails?.bin ?
159
+ `${btResponse.enrichments.cardDetails.bin}****${btResponse.enrichments.cardDetails.last4}` :
160
+ cardData.cardNumber.replace(/\d(?=\d{4})/g, '*'),
161
+ expirationMonth: expiration_month,
162
+ expirationYear: expiration_year,
160
163
  },
161
164
  token: btResponse.id,
162
165
  };
@@ -14,6 +14,7 @@ export interface ProductPrice {
14
14
  export interface ProductVariant {
15
15
  id: string;
16
16
  name: string;
17
+ description: string;
17
18
  sku?: string;
18
19
  weight?: number;
19
20
  imageUrl?: string;
@@ -6,6 +6,7 @@ export { useAuth } from './hooks/useAuth';
6
6
  export { useCheckout } from './hooks/useCheckout';
7
7
  export { useCurrency } from './hooks/useCurrency';
8
8
  export { useCustomer } from './hooks/useCustomer';
9
+ export { useDiscounts } from './hooks/useDiscounts';
9
10
  export { useEnvironment } from './hooks/useEnvironment';
10
11
  export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
11
12
  export { useLocale } from './hooks/useLocale';
@@ -16,22 +17,23 @@ export { usePostPurchases } from './hooks/usePostPurchases';
16
17
  export { useProducts } from './hooks/useProducts';
17
18
  export { useSession } from './hooks/useSession';
18
19
  export { useTagadaContext } from './providers/TagadaProvider';
19
- export { usePluginConfig, useBasePath, getPluginConfig, clearPluginConfigCache, debugPluginConfig } from './hooks/usePluginConfig';
20
+ export { clearPluginConfigCache, debugPluginConfig, getPluginConfig, useBasePath, usePluginConfig } from './hooks/usePluginConfig';
20
21
  export type { PluginConfig } from './hooks/usePluginConfig';
21
- export { useISOData, useCountryOptions, useRegionOptions, getAvailableLanguages } from './hooks/useISOData';
22
+ export { getAvailableLanguages, useCountryOptions, useISOData, useRegionOptions } from './hooks/useISOData';
22
23
  export type { ISOCountry, ISORegion, UseISODataResult } from './hooks/useISOData';
23
- export type { GooglePrediction, GoogleAddressComponent, GooglePlaceDetails, ExtractedAddress, UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult } from './hooks/useGoogleAutocomplete';
24
+ export type { ExtractedAddress, GoogleAddressComponent, GooglePlaceDetails, GooglePrediction, UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult } from './hooks/useGoogleAutocomplete';
24
25
  export { useOrder } from './hooks/useOrder';
25
26
  export type { UseOrderOptions, UseOrderResult } from './hooks/useOrder';
26
27
  export { usePayment } from './hooks/usePayment';
27
28
  export { usePaymentPolling } from './hooks/usePaymentPolling';
28
29
  export { useThreeds } from './hooks/useThreeds';
29
30
  export { useThreedsModal } from './hooks/useThreedsModal';
30
- export type { AuthState, Currency, Customer, Environment, EnvironmentConfig, Locale, Order, OrderAddress, OrderItem, OrderSummary, PickupPoint, Session, Store, } from './types';
31
- export type { CheckoutSessionPreview, CheckoutData, CheckoutInitParams, CheckoutLineItem, CheckoutSession, Promotion, UseCheckoutOptions, UseCheckoutResult, } from './hooks/useCheckout';
31
+ export type { AuthState, Currency, Customer, Environment, EnvironmentConfig, Locale, Order, OrderAddress, OrderItem, OrderSummary, PickupPoint, Session, Store } from './types';
32
+ export type { CheckoutData, CheckoutInitParams, CheckoutLineItem, CheckoutSession, CheckoutSessionPreview, Promotion, UseCheckoutOptions, UseCheckoutResult } from './hooks/useCheckout';
33
+ export type { Discount, DiscountCodeValidation, UseDiscountsOptions, UseDiscountsResult } from './hooks/useDiscounts';
32
34
  export type { OrderBumpPreview, UseOrderBumpOptions, UseOrderBumpResult } from './hooks/useOrderBump';
33
- export type { PostPurchaseOffer, PostPurchaseOfferItem, PostPurchaseOfferLineItem, PostPurchaseOfferSummary, UsePostPurchasesOptions, UsePostPurchasesResult, } from './hooks/usePostPurchases';
35
+ export type { PostPurchaseOffer, PostPurchaseOfferItem, PostPurchaseOfferLineItem, PostPurchaseOfferSummary, UsePostPurchasesOptions, UsePostPurchasesResult } from './hooks/usePostPurchases';
34
36
  export type { Payment, PaymentPollingHook, PollingOptions } from './hooks/usePaymentPolling';
35
- export type { PaymentInstrument, ThreedsChallenge, ThreedsHook, ThreedsOptions, ThreedsProvider, ThreedsSession, } from './hooks/useThreeds';
36
- export type { ApplePayToken, CardPaymentMethod, PaymentHook, PaymentInstrumentResponse, PaymentOptions, PaymentResponse, } from './hooks/usePayment';
37
- export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits, } from './utils/money';
37
+ export type { PaymentInstrument, ThreedsChallenge, ThreedsHook, ThreedsOptions, ThreedsProvider, ThreedsSession } from './hooks/useThreeds';
38
+ export type { ApplePayToken, CardPaymentMethod, PaymentHook, PaymentInstrumentResponse, PaymentOptions, PaymentResponse } from './hooks/usePayment';
39
+ export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits } from './utils/money';
@@ -9,6 +9,7 @@ export { useAuth } from './hooks/useAuth';
9
9
  export { useCheckout } from './hooks/useCheckout';
10
10
  export { useCurrency } from './hooks/useCurrency';
11
11
  export { useCustomer } from './hooks/useCustomer';
12
+ export { useDiscounts } from './hooks/useDiscounts';
12
13
  export { useEnvironment } from './hooks/useEnvironment';
13
14
  export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
14
15
  export { useLocale } from './hooks/useLocale';
@@ -20,9 +21,9 @@ export { useProducts } from './hooks/useProducts';
20
21
  export { useSession } from './hooks/useSession';
21
22
  export { useTagadaContext } from './providers/TagadaProvider';
22
23
  // Plugin configuration hooks
23
- export { usePluginConfig, useBasePath, getPluginConfig, clearPluginConfigCache, debugPluginConfig } from './hooks/usePluginConfig';
24
+ export { clearPluginConfigCache, debugPluginConfig, getPluginConfig, useBasePath, usePluginConfig } from './hooks/usePluginConfig';
24
25
  // ISO Data hooks
25
- export { useISOData, useCountryOptions, useRegionOptions, getAvailableLanguages } from './hooks/useISOData';
26
+ export { getAvailableLanguages, useCountryOptions, useISOData, useRegionOptions } from './hooks/useISOData';
26
27
  // Order hook exports
27
28
  export { useOrder } from './hooks/useOrder';
28
29
  // Payment hooks exports
@@ -33,4 +34,4 @@ export { useThreedsModal } from './hooks/useThreedsModal';
33
34
  // Component exports (if any)
34
35
  // export { SomeComponent } from './components/SomeComponent';
35
36
  // Utility exports
36
- export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits, } from './utils/money';
37
+ export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits } from './utils/money';
@@ -38,11 +38,11 @@ const InitializationLoader = () => (_jsxs("div", { style: {
38
38
  borderTop: '1.5px solid #9ca3af',
39
39
  borderRadius: '50%',
40
40
  animation: 'tagada-spin 1s linear infinite',
41
- } }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
42
- @keyframes tagada-spin {
43
- 0% { transform: rotate(0deg); }
44
- 100% { transform: rotate(360deg); }
45
- }
41
+ } }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
42
+ @keyframes tagada-spin {
43
+ 0% { transform: rotate(0deg); }
44
+ 100% { transform: rotate(360deg); }
45
+ }
46
46
  ` })] }));
47
47
  const TagadaContext = createContext(null);
48
48
  export function TagadaProvider({ children, environment, customApiConfig, debugMode, // Remove default, will be set based on environment
package/package.json CHANGED
@@ -1,78 +1,83 @@
1
- {
2
- "name": "@tagadapay/plugin-sdk",
3
- "version": "2.3.3",
4
- "description": "Modern React SDK for building Tagada Pay plugins",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "exports": {
8
- ".": {
9
- "types": "./dist/index.d.ts",
10
- "import": "./dist/index.js",
11
- "require": "./dist/index.js"
12
- },
13
- "./react": {
14
- "types": "./dist/react/index.d.ts",
15
- "import": "./dist/react/index.js",
16
- "require": "./dist/react/index.js"
17
- }
18
- },
19
- "scripts": {
20
- "build": "tsc",
21
- "clean": "rm -rf dist",
22
- "lint": "echo \"No linting configured\"",
23
- "test": "echo \"No tests yet\" && exit 0",
24
- "dev": "tsc --watch",
25
- "prepublishOnly": "npm run clean && npm run build",
26
- "publish:patch": "npm version patch && npm publish",
27
- "publish:minor": "npm version minor && npm publish",
28
- "publish:major": "npm version major && npm publish",
29
- "publish:beta": "npm version prerelease --preid=beta && npm publish --tag beta",
30
- "publish:alpha": "npm version prerelease --preid=alpha && npm publish --tag alpha",
31
- "version:patch": "npm version patch",
32
- "version:minor": "npm version minor",
33
- "version:major": "npm version major",
34
- "version:beta": "npm version prerelease --preid=beta",
35
- "version:alpha": "npm version prerelease --preid=alpha"
36
- },
37
- "keywords": [
38
- "tagadapay",
39
- "cms",
40
- "plugin",
41
- "sdk",
42
- "react",
43
- "typescript"
44
- ],
45
- "author": "Tagada Pay",
46
- "license": "MIT",
47
- "dependencies": {
48
- "@basis-theory/apple-pay-js": "^2.0.2",
49
- "@basis-theory/basis-theory-js": "^4.30.0",
50
- "@basis-theory/basis-theory-react": "^1.32.5",
51
- "@basis-theory/web-threeds": "^1.0.1",
52
- "axios": "^1.6.0",
53
- "iso3166-2-db": "^2.3.11",
54
- "react-intl": "^7.1.11"
55
- },
56
- "devDependencies": {
57
- "@types/node": "^18.0.0",
58
- "@types/react": "^19",
59
- "@types/react-dom": "^19",
60
- "typescript": "^5.0.0"
61
- },
62
- "peerDependencies": {
63
- "react": "^18.0.0 || ^19.0.0",
64
- "react-dom": "^18.0.0 || ^19.0.0"
65
- },
66
- "files": [
67
- "dist/**/*",
68
- "README.md"
69
- ],
70
- "repository": {
71
- "type": "git",
72
- "url": "git+https://github.com/tagadapay/plugin-sdk.git"
73
- },
74
- "bugs": {
75
- "url": "https://github.com/tagadapay/plugin-sdk/issues"
76
- },
77
- "homepage": "https://github.com/tagadapay/plugin-sdk#readme"
78
- }
1
+ {
2
+ "name": "@tagadapay/plugin-sdk",
3
+ "version": "2.3.5",
4
+ "description": "Modern React SDK for building Tagada Pay plugins",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.js"
12
+ },
13
+ "./react": {
14
+ "types": "./dist/react/index.d.ts",
15
+ "import": "./dist/react/index.js",
16
+ "require": "./dist/react/index.js"
17
+ }
18
+ },
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "clean": "rm -rf dist",
22
+ "lint": "echo \"No linting configured\"",
23
+ "test": "echo \"No tests yet\" && exit 0",
24
+ "dev": "tsc --watch",
25
+ "prepublishOnly": "npm run clean && npm run build",
26
+ "publish:patch": "npm version patch && npm publish",
27
+ "publish:minor": "npm version minor && npm publish",
28
+ "publish:major": "npm version major && npm publish",
29
+ "publish:beta": "npm version prerelease --preid=beta && npm publish --tag beta",
30
+ "publish:alpha": "npm version prerelease --preid=alpha && npm publish --tag alpha",
31
+ "version:patch": "npm version patch",
32
+ "version:minor": "npm version minor",
33
+ "version:major": "npm version major",
34
+ "version:beta": "npm version prerelease --preid=beta",
35
+ "version:alpha": "npm version prerelease --preid=alpha",
36
+ "version:check": "node version-sync.js check",
37
+ "version:sync": "node version-sync.js sync",
38
+ "version:list": "node version-sync.js list",
39
+ "version:next": "node version-sync.js next",
40
+ "postversion": "echo \"✅ Version updated to $(node -p 'require(\"./package.json\").version')\" && git push && git push --tags"
41
+ },
42
+ "keywords": [
43
+ "tagadapay",
44
+ "cms",
45
+ "plugin",
46
+ "sdk",
47
+ "react",
48
+ "typescript"
49
+ ],
50
+ "author": "Tagada Pay",
51
+ "license": "MIT",
52
+ "dependencies": {
53
+ "@basis-theory/apple-pay-js": "^2.0.2",
54
+ "@basis-theory/basis-theory-js": "^4.30.0",
55
+ "@basis-theory/basis-theory-react": "^1.32.5",
56
+ "@basis-theory/web-threeds": "^1.0.1",
57
+ "axios": "^1.6.0",
58
+ "iso3166-2-db": "^2.3.11",
59
+ "react-intl": "^7.1.11"
60
+ },
61
+ "devDependencies": {
62
+ "@types/node": "^18.0.0",
63
+ "@types/react": "^19",
64
+ "@types/react-dom": "^19",
65
+ "typescript": "^5.0.0"
66
+ },
67
+ "peerDependencies": {
68
+ "react": "^18.0.0 || ^19.0.0",
69
+ "react-dom": "^18.0.0 || ^19.0.0"
70
+ },
71
+ "files": [
72
+ "dist/**/*",
73
+ "README.md"
74
+ ],
75
+ "repository": {
76
+ "type": "git",
77
+ "url": "git+https://github.com/tagadapay/plugin-sdk.git"
78
+ },
79
+ "bugs": {
80
+ "url": "https://github.com/tagadapay/plugin-sdk/issues"
81
+ },
82
+ "homepage": "https://github.com/tagadapay/plugin-sdk#readme"
83
+ }