@explorins/pers-sdk 1.6.3 → 1.6.6
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 +63 -37
- package/dist/analytics/index.d.ts +0 -16
- package/dist/analytics/index.d.ts.map +1 -1
- package/dist/analytics.cjs +5 -73
- package/dist/analytics.cjs.map +1 -1
- package/dist/analytics.js +1 -72
- package/dist/analytics.js.map +1 -1
- package/dist/business/index.d.ts +0 -24
- package/dist/business/index.d.ts.map +1 -1
- package/dist/business.cjs +5 -273
- package/dist/business.cjs.map +1 -1
- package/dist/business.js +1 -272
- package/dist/business.js.map +1 -1
- package/dist/campaign/api/campaign-api.d.ts +3 -13
- package/dist/campaign/api/campaign-api.d.ts.map +1 -1
- package/dist/campaign/index.d.ts +0 -34
- package/dist/campaign/index.d.ts.map +1 -1
- package/dist/campaign.cjs +5 -470
- package/dist/campaign.cjs.map +1 -1
- package/dist/campaign.js +1 -469
- package/dist/campaign.js.map +1 -1
- package/dist/chunks/analytics-service-CitlimKJ.cjs +49 -0
- package/dist/chunks/analytics-service-CitlimKJ.cjs.map +1 -0
- package/dist/chunks/analytics-service-CxyrOwel.js +46 -0
- package/dist/chunks/analytics-service-CxyrOwel.js.map +1 -0
- package/dist/chunks/{token-sdk-BW4kkJb3.js → base-token-service-BSXDwrcq.js} +138 -204
- package/dist/chunks/base-token-service-BSXDwrcq.js.map +1 -0
- package/dist/chunks/{token-sdk-CiAbOb6c.cjs → base-token-service-CYuqPPs0.cjs} +140 -207
- package/dist/chunks/base-token-service-CYuqPPs0.cjs.map +1 -0
- package/dist/chunks/business-service-Cq3-oksM.cjs +241 -0
- package/dist/chunks/business-service-Cq3-oksM.cjs.map +1 -0
- package/dist/chunks/business-service-DrC-TNGa.js +238 -0
- package/dist/chunks/business-service-DrC-TNGa.js.map +1 -0
- package/dist/chunks/campaign-service-CWK9I388.cjs +403 -0
- package/dist/chunks/campaign-service-CWK9I388.cjs.map +1 -0
- package/dist/chunks/campaign-service-Dd7gMjC9.js +400 -0
- package/dist/chunks/campaign-service-Dd7gMjC9.js.map +1 -0
- package/dist/chunks/donation-service-CyJS4DIZ.js +47 -0
- package/dist/chunks/donation-service-CyJS4DIZ.js.map +1 -0
- package/dist/chunks/donation-service-D-xFrONi.cjs +50 -0
- package/dist/chunks/donation-service-D-xFrONi.cjs.map +1 -0
- package/dist/chunks/{index-CJ9Jfa4A.js → explorer.utils-Ckll15ja.js} +108 -172
- package/dist/chunks/explorer.utils-Ckll15ja.js.map +1 -0
- package/dist/chunks/{index-CzEluQmf.cjs → explorer.utils-GpskbLl1.cjs} +106 -174
- package/dist/chunks/explorer.utils-GpskbLl1.cjs.map +1 -0
- package/dist/chunks/index-BtDNXaFq.js +13 -0
- package/dist/chunks/index-BtDNXaFq.js.map +1 -0
- package/dist/chunks/index-CMk3Aqkk.cjs +15 -0
- package/dist/chunks/index-CMk3Aqkk.cjs.map +1 -0
- package/dist/chunks/payment-service-B4qx0qiE.cjs +220 -0
- package/dist/chunks/payment-service-B4qx0qiE.cjs.map +1 -0
- package/dist/chunks/payment-service-DfCBFosx.js +217 -0
- package/dist/chunks/payment-service-DfCBFosx.js.map +1 -0
- package/dist/chunks/pers-sdk-CajYwGkL.cjs +5850 -0
- package/dist/chunks/pers-sdk-CajYwGkL.cjs.map +1 -0
- package/dist/chunks/pers-sdk-eO4XUi8w.js +5817 -0
- package/dist/chunks/pers-sdk-eO4XUi8w.js.map +1 -0
- package/dist/chunks/redemption-service-7qbeQxEM.cjs +330 -0
- package/dist/chunks/redemption-service-7qbeQxEM.cjs.map +1 -0
- package/dist/chunks/redemption-service-BT0J5Iy7.js +327 -0
- package/dist/chunks/redemption-service-BT0J5Iy7.js.map +1 -0
- package/dist/chunks/tenant-service-Ba7xrWED.cjs +171 -0
- package/dist/chunks/tenant-service-Ba7xrWED.cjs.map +1 -0
- package/dist/chunks/tenant-service-DELk412y.js +168 -0
- package/dist/chunks/tenant-service-DELk412y.js.map +1 -0
- package/dist/chunks/token-service-BWScn8Qa.cjs +208 -0
- package/dist/chunks/token-service-BWScn8Qa.cjs.map +1 -0
- package/dist/chunks/token-service-CpVwC5Eb.js +205 -0
- package/dist/chunks/token-service-CpVwC5Eb.js.map +1 -0
- package/dist/chunks/user-service-D1Rn4U8u.cjs +153 -0
- package/dist/chunks/user-service-D1Rn4U8u.cjs.map +1 -0
- package/dist/chunks/user-service-D6mTa_WZ.js +150 -0
- package/dist/chunks/user-service-D6mTa_WZ.js.map +1 -0
- package/dist/chunks/{index-BfOoX87y.cjs → web3-chain-service-BYkj61DN.cjs} +1 -33
- package/dist/chunks/web3-chain-service-BYkj61DN.cjs.map +1 -0
- package/dist/chunks/{index-CM21r58m.js → web3-chain-service-DN6tJmvK.js} +2 -31
- package/dist/chunks/web3-chain-service-DN6tJmvK.js.map +1 -0
- package/dist/core/auth/auth-provider.interface.d.ts +32 -69
- package/dist/core/auth/auth-provider.interface.d.ts.map +1 -1
- package/dist/core/auth/default-auth-provider.d.ts +15 -58
- package/dist/core/auth/default-auth-provider.d.ts.map +1 -1
- package/dist/core/auth/index.d.ts +10 -12
- package/dist/core/auth/index.d.ts.map +1 -1
- package/dist/core/auth/refresh-manager.d.ts +18 -0
- package/dist/core/auth/refresh-manager.d.ts.map +1 -0
- package/dist/core/auth/services/auth-service.d.ts +11 -6
- package/dist/core/auth/services/auth-service.d.ts.map +1 -1
- package/dist/core/auth/token-storage.d.ts +27 -47
- package/dist/core/auth/token-storage.d.ts.map +1 -1
- package/dist/core/errors/index.d.ts +1 -5
- package/dist/core/errors/index.d.ts.map +1 -1
- package/dist/core/index.d.ts +4 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/pers-api-client.d.ts +10 -126
- package/dist/core/pers-api-client.d.ts.map +1 -1
- package/dist/core/pers-config.d.ts +8 -3
- package/dist/core/pers-config.d.ts.map +1 -1
- package/dist/core/utils/jwt.function.d.ts.map +1 -1
- package/dist/core.cjs +22 -17
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +13 -13
- package/dist/donation/index.d.ts +0 -15
- package/dist/donation/index.d.ts.map +1 -1
- package/dist/donation.cjs +5 -75
- package/dist/donation.cjs.map +1 -1
- package/dist/donation.js +1 -74
- package/dist/donation.js.map +1 -1
- package/dist/index.cjs +51 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +16 -15
- package/dist/index.js.map +1 -1
- package/dist/managers/analytics-manager.d.ts +290 -10
- package/dist/managers/analytics-manager.d.ts.map +1 -1
- package/dist/managers/auth-manager.d.ts +123 -23
- package/dist/managers/auth-manager.d.ts.map +1 -1
- package/dist/managers/business-manager.d.ts +273 -18
- package/dist/managers/business-manager.d.ts.map +1 -1
- package/dist/managers/campaign-manager.d.ts +585 -46
- package/dist/managers/campaign-manager.d.ts.map +1 -1
- package/dist/managers/donation-manager.d.ts +5 -5
- package/dist/managers/donation-manager.d.ts.map +1 -1
- package/dist/managers/file-manager.d.ts +430 -13
- package/dist/managers/file-manager.d.ts.map +1 -1
- package/dist/managers/purchase-manager.d.ts +340 -15
- package/dist/managers/purchase-manager.d.ts.map +1 -1
- package/dist/managers/redemption-manager.d.ts +450 -27
- package/dist/managers/redemption-manager.d.ts.map +1 -1
- package/dist/managers/tenant-manager.d.ts +5 -5
- package/dist/managers/tenant-manager.d.ts.map +1 -1
- package/dist/managers/token-manager.d.ts +245 -21
- package/dist/managers/token-manager.d.ts.map +1 -1
- package/dist/managers/transaction-manager.d.ts +447 -18
- package/dist/managers/transaction-manager.d.ts.map +1 -1
- package/dist/managers/user-manager.d.ts +216 -14
- package/dist/managers/user-manager.d.ts.map +1 -1
- package/dist/managers/web3-manager.d.ts +4 -4
- package/dist/managers/web3-manager.d.ts.map +1 -1
- package/dist/package.json +9 -2
- package/dist/payment/index.d.ts +0 -21
- package/dist/payment/index.d.ts.map +1 -1
- package/dist/payment.cjs +5 -255
- package/dist/payment.cjs.map +1 -1
- package/dist/payment.js +1 -254
- package/dist/payment.js.map +1 -1
- package/dist/pers-sdk.d.ts +141 -34
- package/dist/pers-sdk.d.ts.map +1 -1
- package/dist/redemption/index.d.ts +0 -25
- package/dist/redemption/index.d.ts.map +1 -1
- package/dist/redemption.cjs +5 -365
- package/dist/redemption.cjs.map +1 -1
- package/dist/redemption.js +1 -364
- package/dist/redemption.js.map +1 -1
- package/dist/tenant/index.d.ts +0 -22
- package/dist/tenant/index.d.ts.map +1 -1
- package/dist/tenant.cjs +5 -203
- package/dist/tenant.cjs.map +1 -1
- package/dist/tenant.js +1 -202
- package/dist/tenant.js.map +1 -1
- package/dist/token.cjs +6 -6
- package/dist/token.js +2 -2
- package/dist/transaction/index.d.ts +0 -22
- package/dist/transaction/index.d.ts.map +1 -1
- package/dist/transaction.cjs +0 -40
- package/dist/transaction.cjs.map +1 -1
- package/dist/transaction.js +1 -40
- package/dist/transaction.js.map +1 -1
- package/dist/user/index.d.ts +0 -25
- package/dist/user/index.d.ts.map +1 -1
- package/dist/user.cjs +5 -185
- package/dist/user.cjs.map +1 -1
- package/dist/user.js +1 -184
- package/dist/user.js.map +1 -1
- package/dist/web3/index.d.ts +0 -11
- package/dist/web3/index.d.ts.map +1 -1
- package/dist/web3-chain/index.d.ts +0 -9
- package/dist/web3-chain/index.d.ts.map +1 -1
- package/dist/web3-chain/services/getWeb3FCD.service.d.ts.map +1 -1
- package/dist/web3-chain.cjs +5 -5
- package/dist/web3-chain.js +2 -1
- package/dist/web3-chain.js.map +1 -1
- package/dist/web3.cjs +6 -10
- package/dist/web3.cjs.map +1 -1
- package/dist/web3.js +1 -4
- package/dist/web3.js.map +1 -1
- package/package.json +9 -2
- package/dist/chunks/base-token-service-D0KANDgM.js +0 -139
- package/dist/chunks/base-token-service-D0KANDgM.js.map +0 -1
- package/dist/chunks/base-token-service-zNfPjHRx.cjs +0 -141
- package/dist/chunks/base-token-service-zNfPjHRx.cjs.map +0 -1
- package/dist/chunks/index-BfOoX87y.cjs.map +0 -1
- package/dist/chunks/index-CJ9Jfa4A.js.map +0 -1
- package/dist/chunks/index-CM21r58m.js.map +0 -1
- package/dist/chunks/index-CzEluQmf.cjs.map +0 -1
- package/dist/chunks/pers-sdk-DbPwFKrf.cjs +0 -3378
- package/dist/chunks/pers-sdk-DbPwFKrf.cjs.map +0 -1
- package/dist/chunks/pers-sdk-Z6MKeFBX.js +0 -3353
- package/dist/chunks/pers-sdk-Z6MKeFBX.js.map +0 -1
- package/dist/chunks/token-sdk-BW4kkJb3.js.map +0 -1
- package/dist/chunks/token-sdk-CiAbOb6c.cjs.map +0 -1
- package/dist/core/auth/auth-constants.d.ts +0 -33
- package/dist/core/auth/auth-constants.d.ts.map +0 -1
- package/dist/core/auth/auth-errors.d.ts +0 -8
- package/dist/core/auth/auth-errors.d.ts.map +0 -1
- package/dist/core/auth/create-auth-provider.d.ts +0 -27
- package/dist/core/auth/create-auth-provider.d.ts.map +0 -1
- package/dist/core/auth/token-refresh.d.ts +0 -91
- package/dist/core/auth/token-refresh.d.ts.map +0 -1
|
@@ -1,3353 +0,0 @@
|
|
|
1
|
-
import { AccountOwnerType } from '@explorins/pers-shared';
|
|
2
|
-
import { createUserSDK } from '../user.js';
|
|
3
|
-
import { createUserStatusSDK } from '../user-status.js';
|
|
4
|
-
import { T as TokenSDK } from './token-sdk-BW4kkJb3.js';
|
|
5
|
-
import { createBusinessSDK } from '../business.js';
|
|
6
|
-
import { createCampaignSDK } from '../campaign.js';
|
|
7
|
-
import { createRedemptionSDK } from '../redemption.js';
|
|
8
|
-
import { createTransactionSDK } from '../transaction.js';
|
|
9
|
-
import { createPaymentSDK } from '../payment.js';
|
|
10
|
-
import { createTenantSDK } from '../tenant.js';
|
|
11
|
-
import { createAnalyticsSDK } from '../analytics.js';
|
|
12
|
-
import { createDonationSDK } from '../donation.js';
|
|
13
|
-
import { c as createWeb3SDK, b as getExplorerUrlByChainId } from './index-CJ9Jfa4A.js';
|
|
14
|
-
import { c as createWeb3ChainSDK } from './index-CM21r58m.js';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* PERS SDK Configuration interfaces and utilities
|
|
18
|
-
*
|
|
19
|
-
* Provides type-safe configuration options for the PERS SDK
|
|
20
|
-
* with sensible defaults for production environments.
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* Default configuration values
|
|
24
|
-
*/
|
|
25
|
-
const DEFAULT_PERS_CONFIG = {
|
|
26
|
-
environment: 'production',
|
|
27
|
-
apiVersion: 'v2',
|
|
28
|
-
timeout: 30000,
|
|
29
|
-
retries: 3,
|
|
30
|
-
tokenRefreshMargin: 60, // Refresh tokens 60 seconds before expiry
|
|
31
|
-
backgroundRefreshThreshold: 30 // Use background refresh if >30s remaining
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* Internal function to construct API root from environment
|
|
35
|
-
* Now defaults to production and v2
|
|
36
|
-
*/
|
|
37
|
-
function buildApiRoot(environment = 'production', version = 'v2') {
|
|
38
|
-
const baseUrls = {
|
|
39
|
-
development: 'https://explorins-loyalty.ngrok.io',
|
|
40
|
-
staging: `https://dev.api.pers.ninja/${version}`,
|
|
41
|
-
production: `https://api.pers.ninja/${version}`
|
|
42
|
-
};
|
|
43
|
-
return `${baseUrls[environment]}`;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Merge user config with defaults
|
|
47
|
-
*/
|
|
48
|
-
function mergeWithDefaults(config) {
|
|
49
|
-
return {
|
|
50
|
-
...DEFAULT_PERS_CONFIG,
|
|
51
|
-
...config,
|
|
52
|
-
environment: config.environment ?? DEFAULT_PERS_CONFIG.environment,
|
|
53
|
-
apiVersion: config.apiVersion ?? DEFAULT_PERS_CONFIG.apiVersion,
|
|
54
|
-
timeout: config.timeout ?? DEFAULT_PERS_CONFIG.timeout,
|
|
55
|
-
retries: config.retries ?? DEFAULT_PERS_CONFIG.retries
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Platform-Agnostic Auth Admin API Client
|
|
61
|
-
*
|
|
62
|
-
* Handles authentication and authorization admin operations using the PERS backend.
|
|
63
|
-
* Uses @explorins/pers-shared DTOs for consistency with backend.
|
|
64
|
-
*
|
|
65
|
-
* Note: Special header handling (bypass-auth-interceptor) may need to be implemented
|
|
66
|
-
* at the PersApiClient level or through a specialized auth client.
|
|
67
|
-
*/
|
|
68
|
-
class AuthApi {
|
|
69
|
-
constructor(apiClient) {
|
|
70
|
-
this.apiClient = apiClient;
|
|
71
|
-
this.basePath = '/auth';
|
|
72
|
-
}
|
|
73
|
-
// ==========================================
|
|
74
|
-
// ADMIN AUTHENTICATION OPERATIONS
|
|
75
|
-
// ==========================================
|
|
76
|
-
/**
|
|
77
|
-
* ADMIN: Login tenant admin with JWT
|
|
78
|
-
* Note: JWT handling and auth bypass headers may need special implementation
|
|
79
|
-
*/
|
|
80
|
-
async loginTenantAdmin(jwt) {
|
|
81
|
-
const body = {
|
|
82
|
-
authToken: jwt,
|
|
83
|
-
authType: AccountOwnerType.TENANT
|
|
84
|
-
};
|
|
85
|
-
return this.apiClient.post(`${this.basePath}/token`, body, { bypassAuth: true });
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Login user with JWT - bypasses auth headers
|
|
89
|
-
*/
|
|
90
|
-
async loginUser(jwt) {
|
|
91
|
-
const body = {
|
|
92
|
-
authToken: jwt,
|
|
93
|
-
authType: AccountOwnerType.USER
|
|
94
|
-
};
|
|
95
|
-
return this.apiClient.post(`${this.basePath}/token`, body, { bypassAuth: true });
|
|
96
|
-
}
|
|
97
|
-
async loginUnAuthenticated(rawLoginData) {
|
|
98
|
-
const body = {
|
|
99
|
-
authToken: '',
|
|
100
|
-
authType: AccountOwnerType.USER,
|
|
101
|
-
rawLoginData
|
|
102
|
-
};
|
|
103
|
-
return this.apiClient.post(`${this.basePath}/token`, body, { bypassAuth: true });
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Refresh access token - bypasses auth headers to prevent circular dependency
|
|
107
|
-
*/
|
|
108
|
-
async refreshAccessToken(refreshToken) {
|
|
109
|
-
// Bypass auth headers for refresh calls to prevent circular dependency
|
|
110
|
-
return this.apiClient.post(`${this.basePath}/refresh`, { refreshToken }, { bypassAuth: true });
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Platform-Agnostic Auth Admin Service
|
|
116
|
-
*
|
|
117
|
-
* Contains auth admin business logic and operations that work across platforms.
|
|
118
|
-
* No framework dependencies - pure TypeScript business logic.
|
|
119
|
-
*
|
|
120
|
-
* Focuses only on actual backend capabilities.
|
|
121
|
-
*/
|
|
122
|
-
class AuthService {
|
|
123
|
-
constructor(authApi, authProvider) {
|
|
124
|
-
this.authApi = authApi;
|
|
125
|
-
this.authProvider = authProvider;
|
|
126
|
-
}
|
|
127
|
-
// ==========================================
|
|
128
|
-
// ADMIN AUTHENTICATION OPERATIONS
|
|
129
|
-
// ==========================================
|
|
130
|
-
/**
|
|
131
|
-
* ADMIN: Login tenant admin with JWT
|
|
132
|
-
* Automatically stores tokens if auth provider supports token storage
|
|
133
|
-
*/
|
|
134
|
-
async loginTenantAdmin(jwt) {
|
|
135
|
-
const response = await this.authApi.loginTenantAdmin(jwt);
|
|
136
|
-
// Store tokens if auth provider supports it
|
|
137
|
-
if (this.authProvider && response.accessToken) {
|
|
138
|
-
await this.storeTokens(response.accessToken, response.refreshToken, 'admin', jwt);
|
|
139
|
-
}
|
|
140
|
-
return response;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Automatically stores tokens if auth provider supports token storage
|
|
144
|
-
*/
|
|
145
|
-
async loginUser(jwt) {
|
|
146
|
-
const response = await this.authApi.loginUser(jwt);
|
|
147
|
-
// Store tokens if auth provider supports it
|
|
148
|
-
if (this.authProvider && response.accessToken) {
|
|
149
|
-
await this.storeTokens(response.accessToken, response.refreshToken, 'user', jwt);
|
|
150
|
-
}
|
|
151
|
-
return response;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Automatically stores tokens if auth provider supports token storage
|
|
155
|
-
*/
|
|
156
|
-
async loginUserWithRawData(rawLoginData) {
|
|
157
|
-
const loginData = {
|
|
158
|
-
externalId: rawLoginData?.externalId,
|
|
159
|
-
email: rawLoginData?.email,
|
|
160
|
-
firstName: rawLoginData?.firstName,
|
|
161
|
-
lastName: rawLoginData?.lastName,
|
|
162
|
-
customData: rawLoginData?.customData
|
|
163
|
-
};
|
|
164
|
-
const response = await this.authApi.loginUnAuthenticated(loginData);
|
|
165
|
-
// Store tokens if auth provider supports it
|
|
166
|
-
if (this.authProvider && response.accessToken) {
|
|
167
|
-
await this.storeTokens(response.accessToken, response.refreshToken, 'user');
|
|
168
|
-
}
|
|
169
|
-
return response;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* ADMIN: Refresh access token
|
|
173
|
-
* Automatically stores new tokens if auth provider supports token storage
|
|
174
|
-
*/
|
|
175
|
-
async refreshAccessToken(refreshToken) {
|
|
176
|
-
// Use provided refresh token or get from auth provider
|
|
177
|
-
const tokenToUse = refreshToken || (this.authProvider?.getRefreshToken ? await this.authProvider.getRefreshToken() : null);
|
|
178
|
-
if (!tokenToUse) {
|
|
179
|
-
throw new Error('No refresh token available for token refresh');
|
|
180
|
-
}
|
|
181
|
-
const response = await this.authApi.refreshAccessToken(tokenToUse);
|
|
182
|
-
// Store new tokens if auth provider supports it
|
|
183
|
-
if (this.authProvider && response.accessToken) {
|
|
184
|
-
await this.storeTokens(response.accessToken, response.refreshToken);
|
|
185
|
-
}
|
|
186
|
-
return response;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Automatic token refresh using stored refresh token
|
|
190
|
-
* Convenience method for 401 error handling
|
|
191
|
-
*/
|
|
192
|
-
async autoRefreshToken() {
|
|
193
|
-
return this.refreshAccessToken(); // Uses stored refresh token
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Clear stored tokens if auth provider supports it
|
|
197
|
-
*/
|
|
198
|
-
async clearTokens() {
|
|
199
|
-
if (this.authProvider?.clearTokens) {
|
|
200
|
-
await this.authProvider.clearTokens();
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Check if we have valid tokens for authentication
|
|
205
|
-
*/
|
|
206
|
-
hasValidAuth() {
|
|
207
|
-
return this.authProvider?.hasValidToken?.() ?? false;
|
|
208
|
-
}
|
|
209
|
-
// ==========================================
|
|
210
|
-
// PRIVATE HELPERS
|
|
211
|
-
// ==========================================
|
|
212
|
-
/**
|
|
213
|
-
* Store tokens using auth provider if it supports token storage
|
|
214
|
-
*/
|
|
215
|
-
async storeTokens(accessToken, refreshToken, authType, providerToken) {
|
|
216
|
-
if (!this.authProvider)
|
|
217
|
-
return;
|
|
218
|
-
try {
|
|
219
|
-
// Store access token
|
|
220
|
-
if (this.authProvider.setAccessToken) {
|
|
221
|
-
await this.authProvider.setAccessToken(accessToken);
|
|
222
|
-
}
|
|
223
|
-
// Store refresh token if provided and supported
|
|
224
|
-
if (refreshToken && this.authProvider.setRefreshToken) {
|
|
225
|
-
await this.authProvider.setRefreshToken(refreshToken);
|
|
226
|
-
}
|
|
227
|
-
// Store provider token if provided and provider supports it
|
|
228
|
-
if (providerToken && 'setProviderToken' in this.authProvider &&
|
|
229
|
-
typeof this.authProvider.setProviderToken === 'function') {
|
|
230
|
-
await this.authProvider.setProviderToken(providerToken);
|
|
231
|
-
}
|
|
232
|
-
// Store auth type if provided and provider supports it
|
|
233
|
-
if (authType && 'setAuthType' in this.authProvider &&
|
|
234
|
-
typeof this.authProvider.setAuthType === 'function') {
|
|
235
|
-
await this.authProvider.setAuthType(authType);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
catch (error) {
|
|
239
|
-
// Don't throw - token storage failure shouldn't break authentication
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Authentication-related constants for type safety
|
|
246
|
-
*/
|
|
247
|
-
/**
|
|
248
|
-
* Storage keys for authentication tokens
|
|
249
|
-
*/
|
|
250
|
-
const AUTH_STORAGE_KEYS = {
|
|
251
|
-
ACCESS_TOKEN: 'pers_access_token',
|
|
252
|
-
REFRESH_TOKEN: 'pers_refresh_token',
|
|
253
|
-
PROVIDER_TOKEN: 'pers_provider_token', // Generic external JWT (Firebase, Auth0, etc.)
|
|
254
|
-
AUTH_TYPE: 'pers_auth_type',
|
|
255
|
-
};
|
|
256
|
-
/**
|
|
257
|
-
* Generate prefixed storage keys for different auth types
|
|
258
|
-
*/
|
|
259
|
-
function createStorageKey(baseKey, authType = 'user') {
|
|
260
|
-
if (baseKey === AUTH_STORAGE_KEYS.ACCESS_TOKEN) {
|
|
261
|
-
return `pers_access_token_${authType}`;
|
|
262
|
-
}
|
|
263
|
-
if (baseKey === AUTH_STORAGE_KEYS.REFRESH_TOKEN) {
|
|
264
|
-
return `pers_refresh_token_${authType}`;
|
|
265
|
-
}
|
|
266
|
-
return baseKey;
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Authentication method types
|
|
270
|
-
*/
|
|
271
|
-
const AUTH_METHODS = {
|
|
272
|
-
GET: 'GET',
|
|
273
|
-
POST: 'POST',
|
|
274
|
-
PUT: 'PUT',
|
|
275
|
-
DELETE: 'DELETE',
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Token Storage Management
|
|
280
|
-
*
|
|
281
|
-
* Handles secure token storage with different strategies
|
|
282
|
-
*/
|
|
283
|
-
/**
|
|
284
|
-
* LocalStorage-based token storage
|
|
285
|
-
*/
|
|
286
|
-
let LocalStorageTokenStorage$1 = class LocalStorageTokenStorage {
|
|
287
|
-
async setToken(key, value) {
|
|
288
|
-
if (typeof localStorage !== 'undefined') {
|
|
289
|
-
localStorage.setItem(key, value);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
async getToken(key) {
|
|
293
|
-
if (typeof localStorage !== 'undefined') {
|
|
294
|
-
return localStorage.getItem(key);
|
|
295
|
-
}
|
|
296
|
-
return null;
|
|
297
|
-
}
|
|
298
|
-
async removeToken(key) {
|
|
299
|
-
if (typeof localStorage !== 'undefined') {
|
|
300
|
-
localStorage.removeItem(key);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
async clear() {
|
|
304
|
-
if (typeof localStorage !== 'undefined') {
|
|
305
|
-
Object.values(AUTH_STORAGE_KEYS).forEach(key => {
|
|
306
|
-
localStorage.removeItem(key);
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
};
|
|
311
|
-
/**
|
|
312
|
-
* Token Manager - High-level token management
|
|
313
|
-
*/
|
|
314
|
-
let TokenManager$1 = class TokenManager {
|
|
315
|
-
constructor(storage = new LocalStorageTokenStorage$1()) {
|
|
316
|
-
this.storage = storage;
|
|
317
|
-
}
|
|
318
|
-
async setAccessToken(token) {
|
|
319
|
-
await this.storage.setToken(AUTH_STORAGE_KEYS.ACCESS_TOKEN, token);
|
|
320
|
-
}
|
|
321
|
-
async getAccessToken() {
|
|
322
|
-
return this.storage.getToken(AUTH_STORAGE_KEYS.ACCESS_TOKEN);
|
|
323
|
-
}
|
|
324
|
-
async setRefreshToken(token) {
|
|
325
|
-
await this.storage.setToken(AUTH_STORAGE_KEYS.REFRESH_TOKEN, token);
|
|
326
|
-
}
|
|
327
|
-
async getRefreshToken() {
|
|
328
|
-
return this.storage.getToken(AUTH_STORAGE_KEYS.REFRESH_TOKEN);
|
|
329
|
-
}
|
|
330
|
-
async getProviderToken() {
|
|
331
|
-
return await this.storage.getToken(AUTH_STORAGE_KEYS.PROVIDER_TOKEN);
|
|
332
|
-
}
|
|
333
|
-
async setTokenData(data) {
|
|
334
|
-
if (data.accessToken) {
|
|
335
|
-
await this.setAccessToken(data.accessToken);
|
|
336
|
-
}
|
|
337
|
-
if (data.refreshToken) {
|
|
338
|
-
await this.setRefreshToken(data.refreshToken);
|
|
339
|
-
}
|
|
340
|
-
// Could store expiration time if needed
|
|
341
|
-
}
|
|
342
|
-
async getTokenData() {
|
|
343
|
-
const accessToken = await this.getAccessToken();
|
|
344
|
-
const refreshToken = await this.getRefreshToken();
|
|
345
|
-
return {
|
|
346
|
-
accessToken: accessToken || undefined,
|
|
347
|
-
refreshToken: refreshToken || undefined
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
async clearAllTokens() {
|
|
351
|
-
await this.storage.clear();
|
|
352
|
-
}
|
|
353
|
-
async hasValidTokens() {
|
|
354
|
-
const accessToken = await this.getAccessToken();
|
|
355
|
-
return !!accessToken;
|
|
356
|
-
}
|
|
357
|
-
async hasRefreshToken() {
|
|
358
|
-
const refreshToken = await this.getRefreshToken();
|
|
359
|
-
return !!refreshToken;
|
|
360
|
-
}
|
|
361
|
-
async removeToken(key) {
|
|
362
|
-
await this.storage.removeToken(key);
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Set auth type (user or admin)
|
|
366
|
-
*/
|
|
367
|
-
async setAuthType(authType) {
|
|
368
|
-
await this.storage.setToken(AUTH_STORAGE_KEYS.AUTH_TYPE, authType);
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* Get stored auth type
|
|
372
|
-
*/
|
|
373
|
-
async getAuthType() {
|
|
374
|
-
const authType = await this.storage.getToken(AUTH_STORAGE_KEYS.AUTH_TYPE);
|
|
375
|
-
return authType;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Clear auth type from storage
|
|
379
|
-
*/
|
|
380
|
-
async clearAuthType() {
|
|
381
|
-
await this.storage.removeToken(AUTH_STORAGE_KEYS.AUTH_TYPE);
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* Set provider token (generic external JWT)
|
|
385
|
-
*/
|
|
386
|
-
async setProviderToken(token) {
|
|
387
|
-
await this.storage.setToken(AUTH_STORAGE_KEYS.PROVIDER_TOKEN, token);
|
|
388
|
-
}
|
|
389
|
-
/**
|
|
390
|
-
* Clear provider token
|
|
391
|
-
*/
|
|
392
|
-
async clearProviderToken() {
|
|
393
|
-
await this.storage.removeToken(AUTH_STORAGE_KEYS.PROVIDER_TOKEN);
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* PERS SDK Error Handling - Optimized for Performance
|
|
399
|
-
*
|
|
400
|
-
* Consolidated API and auth errors for fast SDK performance
|
|
401
|
-
* Uses @explorins/pers-shared when available, fallback to SDK errors
|
|
402
|
-
*/
|
|
403
|
-
// Fast type guards and utilities
|
|
404
|
-
class ErrorUtils {
|
|
405
|
-
/**
|
|
406
|
-
* Fast token expiration detection
|
|
407
|
-
*/
|
|
408
|
-
static isTokenExpired(error) {
|
|
409
|
-
if (typeof error !== 'object' || error === null)
|
|
410
|
-
return false;
|
|
411
|
-
const err = error;
|
|
412
|
-
const apiError = err?.error || err?.response?.data || err;
|
|
413
|
-
const status = err?.status || err?.response?.status || err?.statusCode;
|
|
414
|
-
return apiError?.code === 'TOKEN_EXPIRED' ||
|
|
415
|
-
apiError?.errorCode === 'TOKEN_EXPIRED' ||
|
|
416
|
-
(status === 401 && apiError?.message?.toLowerCase()?.includes('token'));
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* Fast error message extraction
|
|
420
|
-
*/
|
|
421
|
-
static getMessage(error) {
|
|
422
|
-
if (typeof error !== 'object' || error === null)
|
|
423
|
-
return 'Unknown error';
|
|
424
|
-
const err = error;
|
|
425
|
-
const apiError = err?.error || err?.response?.data || err;
|
|
426
|
-
return apiError?.message || apiError?.detail || err?.message || 'Request failed';
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Fast status code extraction
|
|
430
|
-
*/
|
|
431
|
-
static getStatus(error) {
|
|
432
|
-
if (typeof error !== 'object' || error === null)
|
|
433
|
-
return null;
|
|
434
|
-
const err = error;
|
|
435
|
-
return err?.status || err?.statusCode || err?.response?.status || null;
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Fast retryability check
|
|
439
|
-
*/
|
|
440
|
-
static isRetryable(error) {
|
|
441
|
-
if (typeof error !== 'object' || error === null)
|
|
442
|
-
return false;
|
|
443
|
-
const err = error;
|
|
444
|
-
// Check explicit retryable property first (fastest)
|
|
445
|
-
if (typeof err?.retryable === 'boolean')
|
|
446
|
-
return err.retryable;
|
|
447
|
-
// Fast status-based check
|
|
448
|
-
const status = ErrorUtils.getStatus(error);
|
|
449
|
-
return status === null || status >= 500 || status === 429;
|
|
450
|
-
}
|
|
451
|
-
/**
|
|
452
|
-
* Check if error is from PERS API (uses @explorins/pers-shared format)
|
|
453
|
-
*/
|
|
454
|
-
static isPersApiError(error) {
|
|
455
|
-
return typeof error === 'object' && error !== null &&
|
|
456
|
-
'errorCode' in error && 'domain' in error && 'category' in error;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
// SDK-specific error classes for auth flows
|
|
460
|
-
class TokenRefreshNeeded extends Error {
|
|
461
|
-
constructor(refreshToken) {
|
|
462
|
-
super('Token refresh needed');
|
|
463
|
-
this.refreshToken = refreshToken;
|
|
464
|
-
this.errorCode = 'TOKEN_REFRESH_NEEDED';
|
|
465
|
-
this.domain = 'auth';
|
|
466
|
-
this.category = 'SECURITY';
|
|
467
|
-
this.retryable = true;
|
|
468
|
-
this.name = 'TokenRefreshNeeded';
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
class ProviderTokenRefreshNeeded extends Error {
|
|
472
|
-
constructor(providerToken) {
|
|
473
|
-
super('Provider token refresh needed');
|
|
474
|
-
this.providerToken = providerToken;
|
|
475
|
-
this.errorCode = 'PROVIDER_TOKEN_REFRESH_NEEDED';
|
|
476
|
-
this.domain = 'auth';
|
|
477
|
-
this.category = 'SECURITY';
|
|
478
|
-
this.retryable = true;
|
|
479
|
-
this.name = 'ProviderTokenRefreshNeeded';
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
class LogoutRequired extends Error {
|
|
483
|
-
constructor(message) {
|
|
484
|
-
super(message);
|
|
485
|
-
this.errorCode = 'LOGOUT_REQUIRED';
|
|
486
|
-
this.domain = 'auth';
|
|
487
|
-
this.category = 'SECURITY';
|
|
488
|
-
this.retryable = false;
|
|
489
|
-
this.name = 'LogoutRequired';
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
class PersApiError extends Error {
|
|
493
|
-
constructor(message, endpoint, method, status, retryable = false) {
|
|
494
|
-
super(`API request failed: ${message}`);
|
|
495
|
-
this.endpoint = endpoint;
|
|
496
|
-
this.method = method;
|
|
497
|
-
this.status = status;
|
|
498
|
-
this.errorCode = 'PERS_API_ERROR';
|
|
499
|
-
this.domain = 'api';
|
|
500
|
-
this.category = 'TECHNICAL';
|
|
501
|
-
this.name = 'PersApiError';
|
|
502
|
-
this.retryable = retryable;
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
/**
|
|
507
|
-
* Token Refresh Management
|
|
508
|
-
*
|
|
509
|
-
* Handles the 6-step authentication process:
|
|
510
|
-
* 1. Check for provider token → get complete token set from PERS if missing
|
|
511
|
-
* 2. Store all tokens (access, refresh, provider)
|
|
512
|
-
* 3. Use access token for requests
|
|
513
|
-
* 4. Use refresh token if access expires → get new token set, keep provider
|
|
514
|
-
* 5. Fall back to provider token if refresh fails → get fresh token set from PERS
|
|
515
|
-
* 6. Clear all tokens if provider also fails
|
|
516
|
-
*/
|
|
517
|
-
/**
|
|
518
|
-
* Token Refresh Manager
|
|
519
|
-
*
|
|
520
|
-
* Implements the 6-step authentication process:
|
|
521
|
-
* 1. Use provider token to retrieve complete token set from PERS if not present
|
|
522
|
-
* 2. Store all 3 tokens (access, refresh, provider)
|
|
523
|
-
* 3. Use access token for API requests
|
|
524
|
-
* 4. Use refresh token if access expires → get new token set, preserve provider token
|
|
525
|
-
* 5. Fall back to provider token if refresh fails → get fresh token set from PERS
|
|
526
|
-
* 6. Clear all tokens if provider also fails → force logout
|
|
527
|
-
*/
|
|
528
|
-
class TokenRefreshManager {
|
|
529
|
-
constructor(tokenManager, refreshStrategy) {
|
|
530
|
-
this.refreshAttempts = new Map();
|
|
531
|
-
this.MAX_REFRESH_ATTEMPTS = 1;
|
|
532
|
-
this.loginRequiredListeners = [];
|
|
533
|
-
this.tokenManager = tokenManager;
|
|
534
|
-
this.refreshStrategy = refreshStrategy;
|
|
535
|
-
}
|
|
536
|
-
/**
|
|
537
|
-
* Add listener for login required events
|
|
538
|
-
*/
|
|
539
|
-
onLoginRequired(listener) {
|
|
540
|
-
this.loginRequiredListeners.push(listener);
|
|
541
|
-
}
|
|
542
|
-
/**
|
|
543
|
-
* Remove listener for login required events
|
|
544
|
-
*/
|
|
545
|
-
removeLoginRequiredListener(listener) {
|
|
546
|
-
const index = this.loginRequiredListeners.indexOf(listener);
|
|
547
|
-
if (index > -1) {
|
|
548
|
-
this.loginRequiredListeners.splice(index, 1);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Emit login required event to all listeners
|
|
553
|
-
*/
|
|
554
|
-
emitLoginRequired(reason) {
|
|
555
|
-
const event = {
|
|
556
|
-
reason,
|
|
557
|
-
timestamp: new Date()
|
|
558
|
-
};
|
|
559
|
-
this.loginRequiredListeners.forEach(listener => {
|
|
560
|
-
try {
|
|
561
|
-
listener(event);
|
|
562
|
-
}
|
|
563
|
-
catch (error) {
|
|
564
|
-
// Listener error - continuing with other listeners
|
|
565
|
-
}
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
/**
|
|
569
|
-
* Handle token expiration - orchestrates the 6-step authentication process
|
|
570
|
-
* 1. Check for provider token → get complete token set from PERS if missing
|
|
571
|
-
* 2. Store all 3 tokens (access, refresh, provider)
|
|
572
|
-
* 3. Use access token for requests
|
|
573
|
-
* 4. Use refresh token if access expires → get new token set, keep provider
|
|
574
|
-
* 5. Fall back to provider token if refresh fails → get fresh token set from PERS
|
|
575
|
-
* 6. Clear all tokens if provider also fails
|
|
576
|
-
*/
|
|
577
|
-
async handleTokenExpiration() {
|
|
578
|
-
try {
|
|
579
|
-
const accessToken = await this.tokenManager.getAccessToken();
|
|
580
|
-
const refreshToken = await this.tokenManager.getRefreshToken();
|
|
581
|
-
const providerToken = await this.tokenManager.getProviderToken();
|
|
582
|
-
// If we have no PERS tokens but have a provider token, use it to get the complete set
|
|
583
|
-
if (!accessToken && !refreshToken && providerToken) {
|
|
584
|
-
await this.executeProviderTokenFlow(providerToken);
|
|
585
|
-
return;
|
|
586
|
-
}
|
|
587
|
-
// Try refresh token if we have one
|
|
588
|
-
if (refreshToken) {
|
|
589
|
-
await this.executeRefreshTokenFlow(refreshToken);
|
|
590
|
-
return;
|
|
591
|
-
}
|
|
592
|
-
// No refresh token, try provider token
|
|
593
|
-
if (providerToken) {
|
|
594
|
-
await this.executeProviderTokenFlow(providerToken);
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
// No tokens available, require login
|
|
598
|
-
await this.executeAuthCleanup('No authentication tokens available');
|
|
599
|
-
throw new LogoutRequired('No authentication tokens available');
|
|
600
|
-
}
|
|
601
|
-
catch (error) {
|
|
602
|
-
if (error instanceof TokenRefreshNeeded || error instanceof ProviderTokenRefreshNeeded || error instanceof LogoutRequired) {
|
|
603
|
-
throw error;
|
|
604
|
-
}
|
|
605
|
-
// Convert unexpected errors to login requirement
|
|
606
|
-
await this.executeAuthCleanup('Authentication process failed unexpectedly');
|
|
607
|
-
throw new LogoutRequired('Authentication process failed unexpectedly');
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Execute refresh with refresh token (Step 4)
|
|
612
|
-
* Use refresh token to get new access token, preserve provider token
|
|
613
|
-
*/
|
|
614
|
-
async executeRefreshTokenFlow(refreshToken) {
|
|
615
|
-
const attempts = this.refreshAttempts.get(refreshToken) || 0;
|
|
616
|
-
if (attempts >= this.MAX_REFRESH_ATTEMPTS) {
|
|
617
|
-
await this.fallbackToProviderToken();
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
try {
|
|
621
|
-
this.refreshAttempts.set(refreshToken, attempts + 1);
|
|
622
|
-
const result = await this.refreshStrategy.refreshWithRefreshToken(refreshToken);
|
|
623
|
-
await this.storeTokenResult(result);
|
|
624
|
-
this.refreshAttempts.delete(refreshToken);
|
|
625
|
-
}
|
|
626
|
-
catch (error) {
|
|
627
|
-
await this.fallbackToProviderToken();
|
|
628
|
-
}
|
|
629
|
-
} /**
|
|
630
|
-
* Execute refresh with provider token (Step 5)
|
|
631
|
-
* Uses provider token to get a fresh token set from PERS backend
|
|
632
|
-
*/
|
|
633
|
-
async executeProviderTokenFlow(providerToken) {
|
|
634
|
-
try {
|
|
635
|
-
const result = await this.refreshStrategy.refreshWithProviderToken(providerToken);
|
|
636
|
-
await this.storeTokenResult(result);
|
|
637
|
-
this.refreshAttempts.clear();
|
|
638
|
-
}
|
|
639
|
-
catch (error) {
|
|
640
|
-
await this.executeAuthCleanup('Provider token authentication failed - all methods exhausted');
|
|
641
|
-
throw new LogoutRequired('Provider token authentication failed - all methods exhausted');
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
async storeTokenResult(result) {
|
|
645
|
-
await this.tokenManager.setAccessToken(result.accessToken);
|
|
646
|
-
if (result.refreshToken) {
|
|
647
|
-
await this.tokenManager.setRefreshToken(result.refreshToken);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
async fallbackToProviderToken() {
|
|
651
|
-
const providerToken = await this.tokenManager.getProviderToken();
|
|
652
|
-
if (providerToken) {
|
|
653
|
-
try {
|
|
654
|
-
await this.executeProviderTokenFlow(providerToken);
|
|
655
|
-
}
|
|
656
|
-
catch (providerError) {
|
|
657
|
-
await this.executeAuthCleanup('All authentication methods exhausted');
|
|
658
|
-
throw new LogoutRequired('All authentication methods exhausted');
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
else {
|
|
662
|
-
await this.executeAuthCleanup('Refresh failed and no provider token available');
|
|
663
|
-
throw new LogoutRequired('Refresh failed and no provider token available');
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
async clearAuthTokens() {
|
|
667
|
-
await this.tokenManager.removeToken(AUTH_STORAGE_KEYS.ACCESS_TOKEN);
|
|
668
|
-
await this.tokenManager.removeToken(AUTH_STORAGE_KEYS.REFRESH_TOKEN);
|
|
669
|
-
// Clear refresh attempts tracking
|
|
670
|
-
this.refreshAttempts.clear();
|
|
671
|
-
}
|
|
672
|
-
/**
|
|
673
|
-
* Execute authentication cleanup and notify login required (Step 6)
|
|
674
|
-
*/
|
|
675
|
-
async executeAuthCleanup(reason = 'Authentication failed') {
|
|
676
|
-
await this.tokenManager.clearAllTokens();
|
|
677
|
-
this.refreshAttempts.clear();
|
|
678
|
-
this.emitLoginRequired(reason);
|
|
679
|
-
}
|
|
680
|
-
/**
|
|
681
|
-
* Check if an error should trigger token refresh (React Native compatible)
|
|
682
|
-
*/
|
|
683
|
-
shouldRefreshToken(error) {
|
|
684
|
-
return ErrorUtils.isTokenExpired(error);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
/**
|
|
689
|
-
* DefaultAuthRefreshStrategy - Implements the actual refresh logic
|
|
690
|
-
*/
|
|
691
|
-
class DefaultAuthRefreshStrategy {
|
|
692
|
-
constructor(tokenManager, getProviderTokenFn, authApi) {
|
|
693
|
-
this.tokenManager = tokenManager;
|
|
694
|
-
this.getProviderTokenFn = getProviderTokenFn;
|
|
695
|
-
this.authApi = authApi;
|
|
696
|
-
}
|
|
697
|
-
async refreshWithRefreshToken(refreshToken) {
|
|
698
|
-
try {
|
|
699
|
-
const result = await this.authApi.refreshAccessToken(refreshToken);
|
|
700
|
-
if (!result.accessToken) {
|
|
701
|
-
throw new Error('Invalid refresh response: missing accessToken');
|
|
702
|
-
}
|
|
703
|
-
return {
|
|
704
|
-
accessToken: result.accessToken,
|
|
705
|
-
refreshToken: result.refreshToken || refreshToken
|
|
706
|
-
};
|
|
707
|
-
}
|
|
708
|
-
catch (error) {
|
|
709
|
-
throw new Error(`Refresh token invalid or expired: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
async refreshWithProviderToken(providerToken) {
|
|
713
|
-
try {
|
|
714
|
-
const storedAuthType = await this.tokenManager.getAuthType();
|
|
715
|
-
let result;
|
|
716
|
-
if (storedAuthType === 'admin') {
|
|
717
|
-
result = await this.authApi.loginTenantAdmin(providerToken);
|
|
718
|
-
}
|
|
719
|
-
else if (storedAuthType === 'user') {
|
|
720
|
-
result = await this.authApi.loginUser(providerToken);
|
|
721
|
-
}
|
|
722
|
-
else {
|
|
723
|
-
try {
|
|
724
|
-
result = await this.authApi.loginUser(providerToken);
|
|
725
|
-
await this.tokenManager.setAuthType('user');
|
|
726
|
-
}
|
|
727
|
-
catch (userLoginError) {
|
|
728
|
-
result = await this.authApi.loginTenantAdmin(providerToken);
|
|
729
|
-
await this.tokenManager.setAuthType('admin');
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
if (!result.accessToken) {
|
|
733
|
-
throw new Error('Invalid provider login response: missing accessToken');
|
|
734
|
-
}
|
|
735
|
-
return {
|
|
736
|
-
accessToken: result.accessToken,
|
|
737
|
-
refreshToken: result.refreshToken
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
catch (error) {
|
|
741
|
-
throw new Error(`Provider token login failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
/**
|
|
746
|
-
* Default authentication provider with modular architecture
|
|
747
|
-
*
|
|
748
|
-
* Delegates token storage to TokenManager and refresh logic to TokenRefreshManager.
|
|
749
|
-
* Perfect for platform-agnostic usage with reliable error handling.
|
|
750
|
-
*/
|
|
751
|
-
class DefaultAuthProvider {
|
|
752
|
-
constructor(projectKey, authApi) {
|
|
753
|
-
this.projectKey = null;
|
|
754
|
-
this.authApi = null;
|
|
755
|
-
this.authType = 'admin';
|
|
756
|
-
this.projectKey = projectKey || null;
|
|
757
|
-
this.authApi = authApi || null;
|
|
758
|
-
this.tokenManager = new TokenManager$1();
|
|
759
|
-
const refreshStrategy = new DefaultAuthRefreshStrategy(this.tokenManager, () => Promise.resolve(this.getProviderToken()), this.authApi);
|
|
760
|
-
this.tokenRefreshManager = new TokenRefreshManager(this.tokenManager, refreshStrategy);
|
|
761
|
-
}
|
|
762
|
-
async getToken() {
|
|
763
|
-
return await this.tokenManager.getAccessToken();
|
|
764
|
-
}
|
|
765
|
-
async getProjectKey() {
|
|
766
|
-
return this.projectKey;
|
|
767
|
-
}
|
|
768
|
-
/**
|
|
769
|
-
* Centralized token refresh handler - delegates to TokenRefreshManager
|
|
770
|
-
*/
|
|
771
|
-
async onTokenExpired() {
|
|
772
|
-
await this.tokenRefreshManager.handleTokenExpiration();
|
|
773
|
-
}
|
|
774
|
-
/**
|
|
775
|
-
* Check if an error indicates token expiration (React Native compatible)
|
|
776
|
-
*/
|
|
777
|
-
isTokenExpiredError(error) {
|
|
778
|
-
return ErrorUtils.isTokenExpired(error);
|
|
779
|
-
}
|
|
780
|
-
/**
|
|
781
|
-
* Get Firebase or other provider token for fresh JWT request
|
|
782
|
-
* Type-safe method that uses proper storage keys from AUTH_STORAGE_KEYS
|
|
783
|
-
*/
|
|
784
|
-
getProviderToken() {
|
|
785
|
-
if (typeof localStorage !== 'undefined') {
|
|
786
|
-
return localStorage.getItem(AUTH_STORAGE_KEYS.PROVIDER_TOKEN);
|
|
787
|
-
}
|
|
788
|
-
return null;
|
|
789
|
-
}
|
|
790
|
-
async setAccessToken(token) {
|
|
791
|
-
await this.tokenManager.setAccessToken(token);
|
|
792
|
-
}
|
|
793
|
-
async setRefreshToken(token) {
|
|
794
|
-
await this.tokenManager.setRefreshToken(token);
|
|
795
|
-
}
|
|
796
|
-
async getRefreshToken() {
|
|
797
|
-
return await this.tokenManager.getRefreshToken();
|
|
798
|
-
}
|
|
799
|
-
async setProviderToken(token) {
|
|
800
|
-
await this.tokenManager.setProviderToken(token);
|
|
801
|
-
}
|
|
802
|
-
async clearProviderToken() {
|
|
803
|
-
await this.tokenManager.clearProviderToken();
|
|
804
|
-
}
|
|
805
|
-
async clearTokens() {
|
|
806
|
-
await this.tokenManager.clearAllTokens();
|
|
807
|
-
}
|
|
808
|
-
hasValidToken() {
|
|
809
|
-
if (typeof localStorage !== 'undefined') {
|
|
810
|
-
return !!localStorage.getItem(AUTH_STORAGE_KEYS.ACCESS_TOKEN);
|
|
811
|
-
}
|
|
812
|
-
return false;
|
|
813
|
-
}
|
|
814
|
-
hasRefreshToken() {
|
|
815
|
-
if (typeof localStorage !== 'undefined') {
|
|
816
|
-
return !!localStorage.getItem(AUTH_STORAGE_KEYS.REFRESH_TOKEN);
|
|
817
|
-
}
|
|
818
|
-
return false;
|
|
819
|
-
}
|
|
820
|
-
/**
|
|
821
|
-
* Proactively check token expiry and refresh if needed BEFORE making requests
|
|
822
|
-
* Uses smart refresh strategy based on time remaining:
|
|
823
|
-
* - >backgroundThreshold seconds: Background refresh (non-blocking)
|
|
824
|
-
* - <backgroundThreshold seconds: Immediate refresh (blocking)
|
|
825
|
-
*/
|
|
826
|
-
async ensureValidToken(marginSeconds = 60, backgroundThreshold = 30) {
|
|
827
|
-
try {
|
|
828
|
-
const currentToken = await this.getToken();
|
|
829
|
-
// If no token, nothing to check
|
|
830
|
-
if (!currentToken) {
|
|
831
|
-
return;
|
|
832
|
-
}
|
|
833
|
-
// Check if token is expired or will expire within margin
|
|
834
|
-
if (await this.isTokenExpired(marginSeconds)) {
|
|
835
|
-
// Determine refresh strategy based on time remaining
|
|
836
|
-
const timeToExpiry = await this.getTokenTimeToExpiry(currentToken);
|
|
837
|
-
if (timeToExpiry > backgroundThreshold) {
|
|
838
|
-
// Token has enough time left - start background refresh (non-blocking)
|
|
839
|
-
this.startBackgroundRefresh();
|
|
840
|
-
}
|
|
841
|
-
else {
|
|
842
|
-
// Token expiring soon or expired - block and refresh immediately
|
|
843
|
-
const shouldSkipRefresh = await this.isRefreshTokenExpired(marginSeconds);
|
|
844
|
-
if (shouldSkipRefresh) {
|
|
845
|
-
// Both tokens expired - use provider token directly
|
|
846
|
-
await this.handleExpiredRefreshToken();
|
|
847
|
-
}
|
|
848
|
-
else {
|
|
849
|
-
// Normal refresh with refresh token
|
|
850
|
-
if (this.onTokenExpired) {
|
|
851
|
-
await this.onTokenExpired();
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
catch (error) {
|
|
858
|
-
// If token check/refresh fails, the error will be handled by the calling code
|
|
859
|
-
throw error;
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
/**
|
|
863
|
-
* Check if current access token is expired
|
|
864
|
-
*/
|
|
865
|
-
async isTokenExpired(marginSeconds = 60) {
|
|
866
|
-
try {
|
|
867
|
-
const currentToken = await this.getToken();
|
|
868
|
-
if (!currentToken) {
|
|
869
|
-
return true;
|
|
870
|
-
}
|
|
871
|
-
// Import isTokenExpired function here to avoid circular imports
|
|
872
|
-
const { isTokenExpired } = await import('./index-CM21r58m.js').then(function (n) { return n.j; });
|
|
873
|
-
return isTokenExpired(currentToken, marginSeconds);
|
|
874
|
-
}
|
|
875
|
-
catch (error) {
|
|
876
|
-
return true;
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
/**
|
|
880
|
-
* Check if refresh token is expired
|
|
881
|
-
*/
|
|
882
|
-
async isRefreshTokenExpired(marginSeconds = 60) {
|
|
883
|
-
try {
|
|
884
|
-
const refreshToken = await this.tokenManager.getRefreshToken();
|
|
885
|
-
if (!refreshToken) {
|
|
886
|
-
return true; // No refresh token
|
|
887
|
-
}
|
|
888
|
-
// Import isTokenExpired function here to avoid circular imports
|
|
889
|
-
const { isTokenExpired } = await import('./index-CM21r58m.js').then(function (n) { return n.j; });
|
|
890
|
-
return isTokenExpired(refreshToken, marginSeconds);
|
|
891
|
-
}
|
|
892
|
-
catch (error) {
|
|
893
|
-
return true; // Assume expired if we can't check
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
/**
|
|
897
|
-
* Check if both access and refresh tokens are expired
|
|
898
|
-
*/
|
|
899
|
-
async areAllTokensExpired(marginSeconds = 60) {
|
|
900
|
-
const accessTokenExpired = await this.isTokenExpired(marginSeconds);
|
|
901
|
-
const refreshTokenExpired = await this.isRefreshTokenExpired(marginSeconds);
|
|
902
|
-
return accessTokenExpired && refreshTokenExpired;
|
|
903
|
-
}
|
|
904
|
-
/**
|
|
905
|
-
* Get seconds until token expires
|
|
906
|
-
*/
|
|
907
|
-
async getTokenTimeToExpiry(token) {
|
|
908
|
-
try {
|
|
909
|
-
const { isTokenExpired } = await import('./index-CM21r58m.js').then(function (n) { return n.j; });
|
|
910
|
-
const { jwtDecode } = await import('jwt-decode');
|
|
911
|
-
const decoded = jwtDecode(token);
|
|
912
|
-
const currentTime = Math.floor(Date.now() / 1000);
|
|
913
|
-
return Math.max(0, decoded.exp - currentTime);
|
|
914
|
-
}
|
|
915
|
-
catch (error) {
|
|
916
|
-
return 0; // Assume expired if can't decode
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
/**
|
|
920
|
-
* Start refresh in background without blocking current request
|
|
921
|
-
*/
|
|
922
|
-
startBackgroundRefresh() {
|
|
923
|
-
// Use setTimeout to avoid blocking the current request
|
|
924
|
-
setTimeout(async () => {
|
|
925
|
-
try {
|
|
926
|
-
if (this.onTokenExpired) {
|
|
927
|
-
await this.onTokenExpired();
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
catch (error) {
|
|
931
|
-
// Background refresh failed - next request will trigger reactive refresh
|
|
932
|
-
}
|
|
933
|
-
}, 0);
|
|
934
|
-
}
|
|
935
|
-
/**
|
|
936
|
-
* Handle case where refresh token is also expired - use provider token directly
|
|
937
|
-
*/
|
|
938
|
-
async handleExpiredRefreshToken() {
|
|
939
|
-
try {
|
|
940
|
-
// Get provider token if available
|
|
941
|
-
const providerToken = this.getProviderToken();
|
|
942
|
-
if (!providerToken) {
|
|
943
|
-
// No provider token available - let normal refresh handle the failure
|
|
944
|
-
if (this.onTokenExpired) {
|
|
945
|
-
await this.onTokenExpired();
|
|
946
|
-
}
|
|
947
|
-
return;
|
|
948
|
-
}
|
|
949
|
-
// Clear expired PERS tokens and use provider token to get fresh ones
|
|
950
|
-
await this.clearTokens();
|
|
951
|
-
// Trigger refresh which should now use provider token path
|
|
952
|
-
if (this.onTokenExpired) {
|
|
953
|
-
await this.onTokenExpired();
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
catch (error) {
|
|
957
|
-
// If provider token flow fails, let normal refresh handle it
|
|
958
|
-
if (this.onTokenExpired) {
|
|
959
|
-
await this.onTokenExpired();
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
// packages/pers-sdk/src/core/pers-api-client.ts
|
|
966
|
-
/**
|
|
967
|
-
* PERS API Client - Core platform-agnostic client for PERS backend
|
|
968
|
-
*
|
|
969
|
-
* Provides authenticated HTTP client with automatic token management,
|
|
970
|
-
* proactive refresh, and comprehensive error handling.
|
|
971
|
-
*
|
|
972
|
-
* Features:
|
|
973
|
-
* - Automatic token refresh before expiry
|
|
974
|
-
* - Background refresh for optimal performance
|
|
975
|
-
* - Provider token fallback for seamless authentication
|
|
976
|
-
* - Configurable retry and timeout settings
|
|
977
|
-
* - Platform-agnostic design
|
|
978
|
-
*
|
|
979
|
-
* @example
|
|
980
|
-
* ```typescript
|
|
981
|
-
* const client = new PersApiClient(httpClient, {
|
|
982
|
-
* environment: 'production',
|
|
983
|
-
* apiProjectKey: 'your-project-key',
|
|
984
|
-
* authProvider: createAuthProvider({
|
|
985
|
-
* tokenProvider: () => getFirebaseToken()
|
|
986
|
-
* })
|
|
987
|
-
* });
|
|
988
|
-
*
|
|
989
|
-
* // Make authenticated requests
|
|
990
|
-
* const data = await client.get('/users/me');
|
|
991
|
-
* ```
|
|
992
|
-
*/
|
|
993
|
-
class PersApiClient {
|
|
994
|
-
/**
|
|
995
|
-
* Creates a new PERS API Client instance
|
|
996
|
-
*
|
|
997
|
-
* @param httpClient - Platform-specific HTTP client implementation
|
|
998
|
-
* @param config - Configuration options for the API client
|
|
999
|
-
*/
|
|
1000
|
-
constructor(httpClient, config) {
|
|
1001
|
-
this.httpClient = httpClient;
|
|
1002
|
-
this.config = config;
|
|
1003
|
-
// Merge user config with defaults (production + v2)
|
|
1004
|
-
this.mergedConfig = mergeWithDefaults(config);
|
|
1005
|
-
// Build API root from merged environment and version
|
|
1006
|
-
this.apiRoot = buildApiRoot(this.mergedConfig.environment, this.mergedConfig.apiVersion);
|
|
1007
|
-
// Initialize auth services for direct authentication
|
|
1008
|
-
this.authApi = new AuthApi(this);
|
|
1009
|
-
// Auto-create auth provider if none provided
|
|
1010
|
-
if (!this.mergedConfig.authProvider) {
|
|
1011
|
-
this.mergedConfig.authProvider = new DefaultAuthProvider(this.mergedConfig.apiProjectKey, this.authApi);
|
|
1012
|
-
}
|
|
1013
|
-
this.authService = new AuthService(this.authApi, this.mergedConfig.authProvider);
|
|
1014
|
-
}
|
|
1015
|
-
/**
|
|
1016
|
-
* Ensures valid authentication token before making requests
|
|
1017
|
-
*
|
|
1018
|
-
* Implements intelligent refresh strategy:
|
|
1019
|
-
* - Tokens with sufficient time remaining: Background refresh (non-blocking)
|
|
1020
|
-
* - Tokens expiring soon or expired: Immediate refresh (blocking)
|
|
1021
|
-
*
|
|
1022
|
-
* @private
|
|
1023
|
-
* @returns Promise that resolves when token validation is complete
|
|
1024
|
-
*/
|
|
1025
|
-
async ensureValidToken() {
|
|
1026
|
-
if (!this.mergedConfig.authProvider?.ensureValidToken) {
|
|
1027
|
-
return; // Auth provider doesn't support proactive validation
|
|
1028
|
-
}
|
|
1029
|
-
try {
|
|
1030
|
-
const refreshMargin = this.mergedConfig.tokenRefreshMargin || 60;
|
|
1031
|
-
const backgroundThreshold = this.mergedConfig.backgroundRefreshThreshold || 30;
|
|
1032
|
-
await this.mergedConfig.authProvider.ensureValidToken(refreshMargin, backgroundThreshold);
|
|
1033
|
-
}
|
|
1034
|
-
catch (error) {
|
|
1035
|
-
// If token check/refresh fails, continue with request
|
|
1036
|
-
// The reactive error handling will catch any auth issues
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
/**
|
|
1040
|
-
* Get request headers including auth token and project key
|
|
1041
|
-
*/
|
|
1042
|
-
async getHeaders() {
|
|
1043
|
-
const headers = {
|
|
1044
|
-
'Content-Type': 'application/json',
|
|
1045
|
-
};
|
|
1046
|
-
// Add authentication token
|
|
1047
|
-
if (this.mergedConfig.authProvider) {
|
|
1048
|
-
const token = await this.mergedConfig.authProvider.getToken();
|
|
1049
|
-
if (token) {
|
|
1050
|
-
headers['Authorization'] = `Bearer ${token}`;
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
// Add project key
|
|
1054
|
-
if (this.mergedConfig.authProvider) {
|
|
1055
|
-
const projectKey = await this.mergedConfig.authProvider.getProjectKey();
|
|
1056
|
-
if (projectKey) {
|
|
1057
|
-
headers['x-project-key'] = projectKey;
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
else if (this.mergedConfig.apiProjectKey) {
|
|
1061
|
-
// Fallback to config project key if no auth provider
|
|
1062
|
-
headers['x-project-key'] = this.mergedConfig.apiProjectKey;
|
|
1063
|
-
}
|
|
1064
|
-
return headers;
|
|
1065
|
-
}
|
|
1066
|
-
/**
|
|
1067
|
-
* Make a request with proper headers, auth, and error handling
|
|
1068
|
-
*/
|
|
1069
|
-
async request(method, endpoint, body, options) {
|
|
1070
|
-
const { retryCount = 0, responseType = 'json', bypassAuth = false } = options || {};
|
|
1071
|
-
const url = `${this.apiRoot}${endpoint}`;
|
|
1072
|
-
// Proactive token expiry check and refresh BEFORE making the request
|
|
1073
|
-
if (!bypassAuth && this.mergedConfig.authProvider && retryCount === 0) {
|
|
1074
|
-
await this.ensureValidToken();
|
|
1075
|
-
}
|
|
1076
|
-
const requestOptions = {
|
|
1077
|
-
headers: bypassAuth ? await this.getHeadersWithoutAuth() : await this.getHeaders(),
|
|
1078
|
-
timeout: this.mergedConfig.timeout,
|
|
1079
|
-
responseType
|
|
1080
|
-
};
|
|
1081
|
-
// Log API request with auth info
|
|
1082
|
-
// const hasAuth = !!this.mergedConfig.authProvider;
|
|
1083
|
-
endpoint.includes('/export/csv');
|
|
1084
|
-
try {
|
|
1085
|
-
let result;
|
|
1086
|
-
switch (method) {
|
|
1087
|
-
case AUTH_METHODS.GET:
|
|
1088
|
-
result = await this.httpClient.get(url, requestOptions);
|
|
1089
|
-
break;
|
|
1090
|
-
case AUTH_METHODS.POST:
|
|
1091
|
-
result = await this.httpClient.post(url, body, requestOptions);
|
|
1092
|
-
break;
|
|
1093
|
-
case AUTH_METHODS.PUT:
|
|
1094
|
-
result = await this.httpClient.put(url, body, requestOptions);
|
|
1095
|
-
break;
|
|
1096
|
-
case AUTH_METHODS.DELETE:
|
|
1097
|
-
result = await this.httpClient.delete(url, requestOptions);
|
|
1098
|
-
break;
|
|
1099
|
-
default:
|
|
1100
|
-
throw new Error(`Unsupported HTTP method: ${method}`);
|
|
1101
|
-
}
|
|
1102
|
-
return result;
|
|
1103
|
-
}
|
|
1104
|
-
catch (error) {
|
|
1105
|
-
// Error handling - proactive token refresh should prevent most 401s
|
|
1106
|
-
const status = ErrorUtils.getStatus(error);
|
|
1107
|
-
const errorMessage = ErrorUtils.getMessage(error);
|
|
1108
|
-
// Fallback: reactive token refresh only if proactive check missed something
|
|
1109
|
-
if (retryCount === 0 && this.mergedConfig.authProvider && ErrorUtils.isTokenExpired(error)) {
|
|
1110
|
-
try {
|
|
1111
|
-
// Fallback token refresh delegation
|
|
1112
|
-
const result = await this.handleTokenRefreshDelegation(method, endpoint, body, options);
|
|
1113
|
-
if (result !== null) {
|
|
1114
|
-
return result;
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
catch (refreshError) {
|
|
1118
|
-
throw new PersApiError(`Auth failed: ${refreshError.message || refreshError}`, endpoint, method, 401);
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
throw new PersApiError(errorMessage, endpoint, method, status || undefined, ErrorUtils.isRetryable(error));
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
/**
|
|
1125
|
-
* Delegate token refresh to auth provider and handle the results
|
|
1126
|
-
*/
|
|
1127
|
-
async handleTokenRefreshDelegation(method, endpoint, body, options) {
|
|
1128
|
-
try {
|
|
1129
|
-
// Let auth provider handle the refresh process
|
|
1130
|
-
const authProvider = this.mergedConfig.authProvider;
|
|
1131
|
-
if (authProvider?.onTokenExpired) {
|
|
1132
|
-
await authProvider.onTokenExpired();
|
|
1133
|
-
}
|
|
1134
|
-
// If we get here, tokens should be refreshed - retry the request
|
|
1135
|
-
// Auth provider refresh succeeded, retrying...
|
|
1136
|
-
return this.request(method, endpoint, body, { ...options, retryCount: 1 });
|
|
1137
|
-
}
|
|
1138
|
-
catch (refreshError) {
|
|
1139
|
-
// Auth provider handled all refresh attempts and failed
|
|
1140
|
-
// Re-throw the error for the caller to handle
|
|
1141
|
-
throw refreshError;
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
/**
|
|
1145
|
-
* Performs an authenticated GET request
|
|
1146
|
-
*
|
|
1147
|
-
* @template T - Expected response type
|
|
1148
|
-
* @param endpoint - API endpoint path (without base URL)
|
|
1149
|
-
* @param responseType - Expected response format
|
|
1150
|
-
* @returns Promise resolving to typed response data
|
|
1151
|
-
*
|
|
1152
|
-
* @example
|
|
1153
|
-
* ```typescript
|
|
1154
|
-
* const user = await client.get<User>('/users/123');
|
|
1155
|
-
* const csvData = await client.get('/export/data', 'blob');
|
|
1156
|
-
* ```
|
|
1157
|
-
*/
|
|
1158
|
-
async get(endpoint, responseType) {
|
|
1159
|
-
return this.request(AUTH_METHODS.GET, endpoint, undefined, { responseType });
|
|
1160
|
-
}
|
|
1161
|
-
/**
|
|
1162
|
-
* Performs an authenticated POST request
|
|
1163
|
-
*
|
|
1164
|
-
* @template T - Expected response type
|
|
1165
|
-
* @param endpoint - API endpoint path (without base URL)
|
|
1166
|
-
* @param body - Request payload data
|
|
1167
|
-
* @param options - Request options including auth bypass
|
|
1168
|
-
* @returns Promise resolving to typed response data
|
|
1169
|
-
*
|
|
1170
|
-
* @example
|
|
1171
|
-
* ```typescript
|
|
1172
|
-
* const user = await client.post<User>('/users', userData);
|
|
1173
|
-
* const publicData = await client.post('/public/contact', formData, { bypassAuth: true });
|
|
1174
|
-
* ```
|
|
1175
|
-
*/
|
|
1176
|
-
async post(endpoint, body, options) {
|
|
1177
|
-
return this.request(AUTH_METHODS.POST, endpoint, body, options);
|
|
1178
|
-
}
|
|
1179
|
-
/**
|
|
1180
|
-
* Generic PUT request
|
|
1181
|
-
*/
|
|
1182
|
-
async put(endpoint, body) {
|
|
1183
|
-
return this.request(AUTH_METHODS.PUT, endpoint, body);
|
|
1184
|
-
}
|
|
1185
|
-
/**
|
|
1186
|
-
* Generic DELETE request
|
|
1187
|
-
*/
|
|
1188
|
-
async delete(endpoint) {
|
|
1189
|
-
return this.request(AUTH_METHODS.DELETE, endpoint);
|
|
1190
|
-
}
|
|
1191
|
-
/**
|
|
1192
|
-
* Get request headers WITHOUT auth token (for auth operations like refresh/login)
|
|
1193
|
-
*/
|
|
1194
|
-
async getHeadersWithoutAuth() {
|
|
1195
|
-
const headers = {
|
|
1196
|
-
'Content-Type': 'application/json',
|
|
1197
|
-
};
|
|
1198
|
-
// Add project key only (no auth token)
|
|
1199
|
-
if (this.mergedConfig.authProvider) {
|
|
1200
|
-
const projectKey = await this.mergedConfig.authProvider.getProjectKey();
|
|
1201
|
-
if (projectKey) {
|
|
1202
|
-
headers['x-project-key'] = projectKey;
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
else if (this.mergedConfig.apiProjectKey) {
|
|
1206
|
-
headers['x-project-key'] = this.mergedConfig.apiProjectKey;
|
|
1207
|
-
}
|
|
1208
|
-
return headers;
|
|
1209
|
-
}
|
|
1210
|
-
// ==========================================
|
|
1211
|
-
// AUTHENTICATION METHODS
|
|
1212
|
-
// ==========================================
|
|
1213
|
-
/**
|
|
1214
|
-
* Authenticates an admin user using external JWT token
|
|
1215
|
-
*
|
|
1216
|
-
* Exchanges external provider token (Firebase, Auth0, etc.) for PERS access tokens.
|
|
1217
|
-
* Automatically stores received tokens for subsequent requests.
|
|
1218
|
-
*
|
|
1219
|
-
* @param externalJwt - JWT token from external authentication provider
|
|
1220
|
-
* @returns Promise resolving to session context with admin permissions
|
|
1221
|
-
*
|
|
1222
|
-
* @example
|
|
1223
|
-
* ```typescript
|
|
1224
|
-
* const firebaseToken = await getIdToken();
|
|
1225
|
-
* const session = await client.loginAdmin(firebaseToken);
|
|
1226
|
-
* console.log('Admin authenticated:', session.user.email);
|
|
1227
|
-
* ```
|
|
1228
|
-
*/
|
|
1229
|
-
async loginAdmin(externalJwt) {
|
|
1230
|
-
return this.authService.loginTenantAdmin(externalJwt);
|
|
1231
|
-
}
|
|
1232
|
-
/**
|
|
1233
|
-
* Authenticates a regular user using external JWT token
|
|
1234
|
-
*
|
|
1235
|
-
* Exchanges external provider token for PERS access tokens with user-level permissions.
|
|
1236
|
-
* Automatically stores received tokens for subsequent requests.
|
|
1237
|
-
*
|
|
1238
|
-
* @param externalJwt - JWT token from external authentication provider
|
|
1239
|
-
* @returns Promise resolving to session context with user permissions
|
|
1240
|
-
*
|
|
1241
|
-
* @example
|
|
1242
|
-
* ```typescript
|
|
1243
|
-
* const firebaseToken = await getIdToken();
|
|
1244
|
-
* const session = await client.loginUser(firebaseToken);
|
|
1245
|
-
* console.log('User authenticated:', session.user.email);
|
|
1246
|
-
* ```
|
|
1247
|
-
*/
|
|
1248
|
-
async loginUser(externalJwt) {
|
|
1249
|
-
return this.authService.loginUser(externalJwt);
|
|
1250
|
-
}
|
|
1251
|
-
/**
|
|
1252
|
-
* Authenticates a user using raw login data (no external JWT)
|
|
1253
|
-
*
|
|
1254
|
-
* Useful for custom authentication flows where user data is provided directly.
|
|
1255
|
-
* Automatically stores received tokens for subsequent requests.
|
|
1256
|
-
*
|
|
1257
|
-
* @param rawLoginData - Object containing user login data (email, name, etc.)
|
|
1258
|
-
* @return Promise resolving to session context with user permissions
|
|
1259
|
-
*/
|
|
1260
|
-
async loginUserWithRawData(rawLoginData) {
|
|
1261
|
-
return this.authService.loginUserWithRawData(rawLoginData);
|
|
1262
|
-
}
|
|
1263
|
-
/**
|
|
1264
|
-
* Checks if current user has a valid authentication token
|
|
1265
|
-
*
|
|
1266
|
-
* Performs basic token availability check without network requests.
|
|
1267
|
-
* For comprehensive validation including expiry, use isTokenExpired().
|
|
1268
|
-
*
|
|
1269
|
-
* @returns True if valid token exists, false otherwise
|
|
1270
|
-
*
|
|
1271
|
-
* @example
|
|
1272
|
-
* ```typescript
|
|
1273
|
-
* if (client.hasValidAuth()) {
|
|
1274
|
-
* // User is authenticated, proceed with API calls
|
|
1275
|
-
* const data = await client.get('/protected-data');
|
|
1276
|
-
* } else {
|
|
1277
|
-
* // Redirect to login
|
|
1278
|
-
* redirectToLogin();
|
|
1279
|
-
* }
|
|
1280
|
-
* ```
|
|
1281
|
-
*/
|
|
1282
|
-
hasValidAuth() {
|
|
1283
|
-
return this.mergedConfig.authProvider?.hasValidToken?.() || false;
|
|
1284
|
-
}
|
|
1285
|
-
/**
|
|
1286
|
-
* Checks if current access token is expired or expiring soon
|
|
1287
|
-
*
|
|
1288
|
-
* @param marginSeconds - Seconds before expiry to consider token as expired (default: 60)
|
|
1289
|
-
* @returns Promise resolving to true if token is expired/expiring, false if valid
|
|
1290
|
-
*
|
|
1291
|
-
* @example
|
|
1292
|
-
* ```typescript
|
|
1293
|
-
* if (await client.isTokenExpired(120)) {
|
|
1294
|
-
* console.log('Token expires within 2 minutes');
|
|
1295
|
-
* // Optionally trigger manual refresh
|
|
1296
|
-
* }
|
|
1297
|
-
* ```
|
|
1298
|
-
*/
|
|
1299
|
-
async isTokenExpired(marginSeconds = 60) {
|
|
1300
|
-
if (!this.mergedConfig.authProvider?.isTokenExpired) {
|
|
1301
|
-
return true; // No auth provider or doesn't support expiry checking
|
|
1302
|
-
}
|
|
1303
|
-
try {
|
|
1304
|
-
return await this.mergedConfig.authProvider.isTokenExpired(marginSeconds);
|
|
1305
|
-
}
|
|
1306
|
-
catch (error) {
|
|
1307
|
-
return true;
|
|
1308
|
-
}
|
|
1309
|
-
}
|
|
1310
|
-
/**
|
|
1311
|
-
* Checks if both access and refresh tokens are expired
|
|
1312
|
-
*
|
|
1313
|
-
* Useful for determining if full re-authentication is required.
|
|
1314
|
-
*
|
|
1315
|
-
* @param marginSeconds - Seconds before expiry to consider tokens as expired (default: 60)
|
|
1316
|
-
* @returns Promise resolving to true if both tokens expired, false otherwise
|
|
1317
|
-
*
|
|
1318
|
-
* @example
|
|
1319
|
-
* ```typescript
|
|
1320
|
-
* if (await client.areAllTokensExpired()) {
|
|
1321
|
-
* // Full re-authentication required
|
|
1322
|
-
* await redirectToLogin();
|
|
1323
|
-
* }
|
|
1324
|
-
* ```
|
|
1325
|
-
*/
|
|
1326
|
-
async areAllTokensExpired(marginSeconds = 60) {
|
|
1327
|
-
if (!this.mergedConfig.authProvider?.areAllTokensExpired) {
|
|
1328
|
-
// Fallback to checking access token only
|
|
1329
|
-
return await this.isTokenExpired(marginSeconds);
|
|
1330
|
-
}
|
|
1331
|
-
return await this.mergedConfig.authProvider.areAllTokensExpired(marginSeconds);
|
|
1332
|
-
}
|
|
1333
|
-
/**
|
|
1334
|
-
* Refresh access token using stored refresh token
|
|
1335
|
-
*
|
|
1336
|
-
* @param refreshToken - Optional refresh token, uses stored token if not provided
|
|
1337
|
-
* @returns Promise resolving to new auth tokens
|
|
1338
|
-
*
|
|
1339
|
-
* @example
|
|
1340
|
-
* ```typescript
|
|
1341
|
-
* try {
|
|
1342
|
-
* const tokens = await client.refreshTokens();
|
|
1343
|
-
* console.log('Tokens refreshed successfully');
|
|
1344
|
-
* } catch (error) {
|
|
1345
|
-
* console.error('Token refresh failed:', error);
|
|
1346
|
-
* }
|
|
1347
|
-
* ```
|
|
1348
|
-
*/
|
|
1349
|
-
async refreshTokens(refreshToken) {
|
|
1350
|
-
return this.authService.refreshAccessToken(refreshToken);
|
|
1351
|
-
}
|
|
1352
|
-
/**
|
|
1353
|
-
* Get current configuration (returns merged config)
|
|
1354
|
-
*/
|
|
1355
|
-
getConfig() {
|
|
1356
|
-
return this.mergedConfig;
|
|
1357
|
-
}
|
|
1358
|
-
/**
|
|
1359
|
-
* Get original user configuration
|
|
1360
|
-
*/
|
|
1361
|
-
getOriginalConfig() {
|
|
1362
|
-
return this.config;
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
|
|
1366
|
-
/**
|
|
1367
|
-
* Memory-based token storage (default)
|
|
1368
|
-
*/
|
|
1369
|
-
class MemoryTokenStorage {
|
|
1370
|
-
constructor() {
|
|
1371
|
-
this.storage = new Map();
|
|
1372
|
-
}
|
|
1373
|
-
async setItem(key, value) {
|
|
1374
|
-
this.storage.set(key, value);
|
|
1375
|
-
}
|
|
1376
|
-
async getItem(key) {
|
|
1377
|
-
return this.storage.get(key) || null;
|
|
1378
|
-
}
|
|
1379
|
-
async removeItem(key) {
|
|
1380
|
-
this.storage.delete(key);
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
/**
|
|
1384
|
-
* localStorage-based token storage (browser only)
|
|
1385
|
-
*/
|
|
1386
|
-
class LocalStorageTokenStorage {
|
|
1387
|
-
async setItem(key, value) {
|
|
1388
|
-
if (typeof localStorage !== 'undefined') {
|
|
1389
|
-
localStorage.setItem(key, value);
|
|
1390
|
-
}
|
|
1391
|
-
else {
|
|
1392
|
-
throw new Error('localStorage is not available in this environment');
|
|
1393
|
-
}
|
|
1394
|
-
}
|
|
1395
|
-
async getItem(key) {
|
|
1396
|
-
if (typeof localStorage !== 'undefined') {
|
|
1397
|
-
return localStorage.getItem(key);
|
|
1398
|
-
}
|
|
1399
|
-
return null;
|
|
1400
|
-
}
|
|
1401
|
-
async removeItem(key) {
|
|
1402
|
-
if (typeof localStorage !== 'undefined') {
|
|
1403
|
-
localStorage.removeItem(key);
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
}
|
|
1407
|
-
/**
|
|
1408
|
-
* Creates a platform-agnostic AuthProvider from simple configuration
|
|
1409
|
-
*
|
|
1410
|
-
* This factory function is completely platform-agnostic and can be used
|
|
1411
|
-
* across Angular, React, Vue, Node.js, or any other JavaScript environment.
|
|
1412
|
-
*
|
|
1413
|
-
* Features:
|
|
1414
|
-
* - Token caching with refresh support
|
|
1415
|
-
* - Automatic token refresh on expiration
|
|
1416
|
-
* - Configurable token providers
|
|
1417
|
-
* - Token storage (memory, localStorage, custom)
|
|
1418
|
-
* - Platform-independent
|
|
1419
|
-
*
|
|
1420
|
-
* @param config - Simple auth configuration
|
|
1421
|
-
* @returns AuthProvider implementation
|
|
1422
|
-
*/
|
|
1423
|
-
function createAuthProvider(config) {
|
|
1424
|
-
// Initialize token storage
|
|
1425
|
-
let tokenStorage;
|
|
1426
|
-
switch (config.tokenStorage) {
|
|
1427
|
-
case 'localStorage':
|
|
1428
|
-
tokenStorage = new LocalStorageTokenStorage();
|
|
1429
|
-
break;
|
|
1430
|
-
case 'custom':
|
|
1431
|
-
if (!config.customTokenStorage) {
|
|
1432
|
-
throw new Error('Custom token storage configuration is required when tokenStorage is "custom"');
|
|
1433
|
-
}
|
|
1434
|
-
tokenStorage = config.customTokenStorage;
|
|
1435
|
-
break;
|
|
1436
|
-
case 'memory':
|
|
1437
|
-
default:
|
|
1438
|
-
tokenStorage = new MemoryTokenStorage();
|
|
1439
|
-
break;
|
|
1440
|
-
}
|
|
1441
|
-
// Token storage keys
|
|
1442
|
-
const ACCESS_TOKEN_KEY = createStorageKey(AUTH_STORAGE_KEYS.ACCESS_TOKEN, config.authType || 'user');
|
|
1443
|
-
const REFRESH_TOKEN_KEY = createStorageKey(AUTH_STORAGE_KEYS.REFRESH_TOKEN, config.authType || 'user');
|
|
1444
|
-
// Store current token for refresh scenarios and caching
|
|
1445
|
-
let currentToken = config.token || null;
|
|
1446
|
-
let isRefreshing = false; // Prevent concurrent refresh attempts
|
|
1447
|
-
let refreshPromise = null;
|
|
1448
|
-
return {
|
|
1449
|
-
authType: config.authType || 'user',
|
|
1450
|
-
async getToken() {
|
|
1451
|
-
// If currently refreshing, wait for it to complete
|
|
1452
|
-
if (isRefreshing && refreshPromise) {
|
|
1453
|
-
await refreshPromise;
|
|
1454
|
-
return currentToken;
|
|
1455
|
-
}
|
|
1456
|
-
// Use cached current token (updated after refresh)
|
|
1457
|
-
if (currentToken) {
|
|
1458
|
-
return currentToken;
|
|
1459
|
-
}
|
|
1460
|
-
// Try to get token from storage
|
|
1461
|
-
try {
|
|
1462
|
-
const storedToken = await tokenStorage.getItem(ACCESS_TOKEN_KEY);
|
|
1463
|
-
if (storedToken) {
|
|
1464
|
-
currentToken = storedToken;
|
|
1465
|
-
return storedToken;
|
|
1466
|
-
}
|
|
1467
|
-
}
|
|
1468
|
-
catch (error) {
|
|
1469
|
-
// Token retrieval failed - continuing without storage
|
|
1470
|
-
}
|
|
1471
|
-
// Custom token provider function (always fresh)
|
|
1472
|
-
if (config.tokenProvider) {
|
|
1473
|
-
const token = await config.tokenProvider();
|
|
1474
|
-
currentToken = token; // Cache for future calls
|
|
1475
|
-
return token;
|
|
1476
|
-
}
|
|
1477
|
-
// No token available
|
|
1478
|
-
return null;
|
|
1479
|
-
},
|
|
1480
|
-
async getProjectKey() {
|
|
1481
|
-
return config.projectKey || null;
|
|
1482
|
-
},
|
|
1483
|
-
// Token storage methods
|
|
1484
|
-
async setAccessToken(token) {
|
|
1485
|
-
currentToken = token;
|
|
1486
|
-
try {
|
|
1487
|
-
await tokenStorage.setItem(ACCESS_TOKEN_KEY, token);
|
|
1488
|
-
}
|
|
1489
|
-
catch (error) {
|
|
1490
|
-
throw error;
|
|
1491
|
-
}
|
|
1492
|
-
},
|
|
1493
|
-
async setRefreshToken(token) {
|
|
1494
|
-
try {
|
|
1495
|
-
await tokenStorage.setItem(REFRESH_TOKEN_KEY, token);
|
|
1496
|
-
}
|
|
1497
|
-
catch (error) {
|
|
1498
|
-
throw error;
|
|
1499
|
-
}
|
|
1500
|
-
},
|
|
1501
|
-
async getRefreshToken() {
|
|
1502
|
-
try {
|
|
1503
|
-
return await tokenStorage.getItem(REFRESH_TOKEN_KEY);
|
|
1504
|
-
}
|
|
1505
|
-
catch (error) {
|
|
1506
|
-
return null;
|
|
1507
|
-
}
|
|
1508
|
-
},
|
|
1509
|
-
async clearTokens() {
|
|
1510
|
-
currentToken = null;
|
|
1511
|
-
try {
|
|
1512
|
-
await Promise.all([
|
|
1513
|
-
tokenStorage.removeItem(ACCESS_TOKEN_KEY),
|
|
1514
|
-
tokenStorage.removeItem(REFRESH_TOKEN_KEY)
|
|
1515
|
-
]);
|
|
1516
|
-
}
|
|
1517
|
-
catch (error) {
|
|
1518
|
-
throw error;
|
|
1519
|
-
}
|
|
1520
|
-
},
|
|
1521
|
-
async onTokenExpired() {
|
|
1522
|
-
// Prevent concurrent refresh attempts
|
|
1523
|
-
if (isRefreshing) {
|
|
1524
|
-
if (refreshPromise) {
|
|
1525
|
-
await refreshPromise;
|
|
1526
|
-
}
|
|
1527
|
-
return;
|
|
1528
|
-
}
|
|
1529
|
-
// No refresh logic provided
|
|
1530
|
-
if (!config.onTokenExpired) {
|
|
1531
|
-
currentToken = null;
|
|
1532
|
-
try {
|
|
1533
|
-
await tokenStorage.removeItem(ACCESS_TOKEN_KEY);
|
|
1534
|
-
}
|
|
1535
|
-
catch (error) {
|
|
1536
|
-
// Token clearing failed - continuing
|
|
1537
|
-
}
|
|
1538
|
-
return;
|
|
1539
|
-
}
|
|
1540
|
-
// Start refresh process
|
|
1541
|
-
isRefreshing = true;
|
|
1542
|
-
refreshPromise = (async () => {
|
|
1543
|
-
try {
|
|
1544
|
-
// Execute refresh logic (should update token source)
|
|
1545
|
-
await config.onTokenExpired();
|
|
1546
|
-
// After refresh, get the new token
|
|
1547
|
-
if (config.tokenProvider) {
|
|
1548
|
-
const newToken = await config.tokenProvider();
|
|
1549
|
-
if (newToken && newToken !== currentToken) {
|
|
1550
|
-
currentToken = newToken;
|
|
1551
|
-
// Store the new token
|
|
1552
|
-
try {
|
|
1553
|
-
await tokenStorage.setItem(ACCESS_TOKEN_KEY, newToken);
|
|
1554
|
-
}
|
|
1555
|
-
catch (error) {
|
|
1556
|
-
// Token storage failed - token still valid in memory
|
|
1557
|
-
}
|
|
1558
|
-
// Notify about successful token refresh
|
|
1559
|
-
if (config.onTokenRefreshed) {
|
|
1560
|
-
config.onTokenRefreshed(newToken);
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
else {
|
|
1564
|
-
currentToken = null;
|
|
1565
|
-
try {
|
|
1566
|
-
await tokenStorage.removeItem(ACCESS_TOKEN_KEY);
|
|
1567
|
-
}
|
|
1568
|
-
catch (error) {
|
|
1569
|
-
// Token clearing failed - continuing
|
|
1570
|
-
}
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
else {
|
|
1574
|
-
// For static token configs, clear the token since we can't refresh
|
|
1575
|
-
currentToken = null;
|
|
1576
|
-
try {
|
|
1577
|
-
await tokenStorage.removeItem(ACCESS_TOKEN_KEY);
|
|
1578
|
-
}
|
|
1579
|
-
catch (error) {
|
|
1580
|
-
// Token clearing failed - continuing
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
}
|
|
1584
|
-
catch (error) {
|
|
1585
|
-
currentToken = null; // Clear token on refresh failure
|
|
1586
|
-
try {
|
|
1587
|
-
await tokenStorage.removeItem(ACCESS_TOKEN_KEY);
|
|
1588
|
-
}
|
|
1589
|
-
catch (storageError) {
|
|
1590
|
-
// Token clearing failed - continuing
|
|
1591
|
-
}
|
|
1592
|
-
throw error; // Re-throw to let SDK handle the error
|
|
1593
|
-
}
|
|
1594
|
-
finally {
|
|
1595
|
-
isRefreshing = false;
|
|
1596
|
-
refreshPromise = null;
|
|
1597
|
-
}
|
|
1598
|
-
})();
|
|
1599
|
-
await refreshPromise;
|
|
1600
|
-
}
|
|
1601
|
-
};
|
|
1602
|
-
}
|
|
1603
|
-
/**
|
|
1604
|
-
* Platform-specific localStorage token provider for browsers
|
|
1605
|
-
* This is a convenience function for browser environments
|
|
1606
|
-
*/
|
|
1607
|
-
/* export function createBrowserTokenProvider(tokenKey: string = 'userJwt'): () => Promise<string | null> {
|
|
1608
|
-
return async () => {
|
|
1609
|
-
if (typeof localStorage !== 'undefined') {
|
|
1610
|
-
return localStorage.getItem(tokenKey);
|
|
1611
|
-
}
|
|
1612
|
-
return null;
|
|
1613
|
-
};
|
|
1614
|
-
} */
|
|
1615
|
-
/**
|
|
1616
|
-
* Platform-specific environment variable token provider for Node.js
|
|
1617
|
-
* This is a convenience function for Node.js environments
|
|
1618
|
-
*/
|
|
1619
|
-
/* export function createNodeTokenProvider(envVar: string = 'JWT_TOKEN'): () => Promise<string | null> {
|
|
1620
|
-
return async () => {
|
|
1621
|
-
if (typeof process !== 'undefined' && process.env) {
|
|
1622
|
-
return process.env[envVar] || null;
|
|
1623
|
-
}
|
|
1624
|
-
return null;
|
|
1625
|
-
};
|
|
1626
|
-
} */
|
|
1627
|
-
|
|
1628
|
-
/**
|
|
1629
|
-
* Authentication Manager - Clean, high-level interface for authentication operations
|
|
1630
|
-
*
|
|
1631
|
-
* Provides a simplified API for common authentication tasks while maintaining
|
|
1632
|
-
* access to the underlying API client for advanced use cases.
|
|
1633
|
-
*/
|
|
1634
|
-
class AuthManager {
|
|
1635
|
-
constructor(apiClient) {
|
|
1636
|
-
this.apiClient = apiClient;
|
|
1637
|
-
}
|
|
1638
|
-
/**
|
|
1639
|
-
* Login with JWT token
|
|
1640
|
-
*
|
|
1641
|
-
* @param jwtToken - JWT token to authenticate with
|
|
1642
|
-
* @param userType - Type of user ('user' | 'admin')
|
|
1643
|
-
* @returns Promise resolving to authentication response
|
|
1644
|
-
*/
|
|
1645
|
-
async loginWithToken(jwtToken, userType = 'user') {
|
|
1646
|
-
return userType === 'admin'
|
|
1647
|
-
? this.apiClient.loginAdmin(jwtToken)
|
|
1648
|
-
: this.apiClient.loginUser(jwtToken);
|
|
1649
|
-
}
|
|
1650
|
-
/**
|
|
1651
|
-
* Login with raw user data
|
|
1652
|
-
*
|
|
1653
|
-
* @param rawUserData - Raw user data for authentication
|
|
1654
|
-
* @returns Promise resolving to authentication response
|
|
1655
|
-
*/
|
|
1656
|
-
async loginWithRawData(rawUserData) {
|
|
1657
|
-
return this.apiClient.loginUserWithRawData(rawUserData);
|
|
1658
|
-
}
|
|
1659
|
-
/**
|
|
1660
|
-
* Get current authenticated user
|
|
1661
|
-
*
|
|
1662
|
-
* @returns Promise resolving to current user data
|
|
1663
|
-
*/
|
|
1664
|
-
async getCurrentUser() {
|
|
1665
|
-
return this.apiClient.get('/users/me');
|
|
1666
|
-
}
|
|
1667
|
-
/**
|
|
1668
|
-
* Refresh current user data
|
|
1669
|
-
*
|
|
1670
|
-
* @returns Promise resolving to updated user data
|
|
1671
|
-
*/
|
|
1672
|
-
async refreshUserData() {
|
|
1673
|
-
return this.getCurrentUser();
|
|
1674
|
-
}
|
|
1675
|
-
/**
|
|
1676
|
-
* Check if user is authenticated
|
|
1677
|
-
*
|
|
1678
|
-
* @returns Promise resolving to boolean indicating authentication status
|
|
1679
|
-
*/
|
|
1680
|
-
async isAuthenticated() {
|
|
1681
|
-
try {
|
|
1682
|
-
await this.getCurrentUser();
|
|
1683
|
-
return true;
|
|
1684
|
-
}
|
|
1685
|
-
catch {
|
|
1686
|
-
return false;
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
/**
|
|
1690
|
-
* Refresh access token using stored refresh token
|
|
1691
|
-
*
|
|
1692
|
-
* @param refreshToken - Optional refresh token, uses stored token if not provided
|
|
1693
|
-
* @returns Promise resolving to new auth tokens
|
|
1694
|
-
*/
|
|
1695
|
-
async refreshTokens(refreshToken) {
|
|
1696
|
-
return this.apiClient.refreshTokens(refreshToken);
|
|
1697
|
-
}
|
|
1698
|
-
/**
|
|
1699
|
-
* Clear stored authentication tokens
|
|
1700
|
-
*
|
|
1701
|
-
* @returns Promise that resolves when tokens are cleared
|
|
1702
|
-
*/
|
|
1703
|
-
async clearAuth() {
|
|
1704
|
-
// Use auth provider to clear tokens if available
|
|
1705
|
-
const authProvider = this.apiClient.getConfig().authProvider;
|
|
1706
|
-
if (authProvider?.clearTokens) {
|
|
1707
|
-
await authProvider.clearTokens();
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
/**
|
|
1711
|
-
* Check if SDK has valid authentication
|
|
1712
|
-
*
|
|
1713
|
-
* @returns Boolean indicating if valid authentication exists
|
|
1714
|
-
*/
|
|
1715
|
-
hasValidAuth() {
|
|
1716
|
-
return this.apiClient.hasValidAuth();
|
|
1717
|
-
}
|
|
1718
|
-
/**
|
|
1719
|
-
* Admin login with JWT token
|
|
1720
|
-
*
|
|
1721
|
-
* @param jwt - JWT token for admin authentication
|
|
1722
|
-
* @returns Promise resolving to authentication context
|
|
1723
|
-
*/
|
|
1724
|
-
async loginAdmin(jwt) {
|
|
1725
|
-
return this.apiClient.loginAdmin(jwt);
|
|
1726
|
-
}
|
|
1727
|
-
/**
|
|
1728
|
-
* User login with JWT token
|
|
1729
|
-
*
|
|
1730
|
-
* @param jwt - JWT token for user authentication
|
|
1731
|
-
* @returns Promise resolving to authentication context
|
|
1732
|
-
*/
|
|
1733
|
-
async loginUser(jwt) {
|
|
1734
|
-
return this.apiClient.loginUser(jwt);
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
|
|
1738
|
-
/**
|
|
1739
|
-
* User Manager - Clean, high-level interface for user operations
|
|
1740
|
-
*
|
|
1741
|
-
* Provides a simplified API for common user management tasks while maintaining
|
|
1742
|
-
* access to the full user SDK for advanced use cases.
|
|
1743
|
-
*/
|
|
1744
|
-
class UserManager {
|
|
1745
|
-
constructor(apiClient) {
|
|
1746
|
-
this.apiClient = apiClient;
|
|
1747
|
-
this.userSDK = createUserSDK(apiClient);
|
|
1748
|
-
}
|
|
1749
|
-
/**
|
|
1750
|
-
* Get current user profile
|
|
1751
|
-
*
|
|
1752
|
-
* @returns Promise resolving to current user data
|
|
1753
|
-
*/
|
|
1754
|
-
async getCurrentUser() {
|
|
1755
|
-
return this.userSDK.getRemoteUser();
|
|
1756
|
-
}
|
|
1757
|
-
/**
|
|
1758
|
-
* Update current user profile
|
|
1759
|
-
*
|
|
1760
|
-
* @param userData - User data to update
|
|
1761
|
-
* @returns Promise resolving to updated user data
|
|
1762
|
-
*/
|
|
1763
|
-
async updateCurrentUser(userData) {
|
|
1764
|
-
return this.userSDK.updateRemoteUser(userData);
|
|
1765
|
-
}
|
|
1766
|
-
/**
|
|
1767
|
-
* Get user by unique identifier
|
|
1768
|
-
*
|
|
1769
|
-
* @param identifier - Unique identifier for the user
|
|
1770
|
-
* @returns Promise resolving to user data
|
|
1771
|
-
*/
|
|
1772
|
-
async getUserById(identifier) {
|
|
1773
|
-
return this.userSDK.getUserByUniqueIdentifier(identifier);
|
|
1774
|
-
}
|
|
1775
|
-
/**
|
|
1776
|
-
* Get all users public profiles with optional filtering
|
|
1777
|
-
*
|
|
1778
|
-
* @param filter - Optional filter criteria
|
|
1779
|
-
* @returns Promise resolving to array of user public profiles
|
|
1780
|
-
*/
|
|
1781
|
-
async getAllUsersPublic(filter) {
|
|
1782
|
-
return this.userSDK.getAllUsersPublicProfiles(filter || null);
|
|
1783
|
-
}
|
|
1784
|
-
/**
|
|
1785
|
-
* Admin: Get all users
|
|
1786
|
-
*
|
|
1787
|
-
* @returns Promise resolving to array of all users
|
|
1788
|
-
*/
|
|
1789
|
-
async getAllUsers() {
|
|
1790
|
-
return this.userSDK.getAllRemoteUsers();
|
|
1791
|
-
}
|
|
1792
|
-
/**
|
|
1793
|
-
* Admin: Update user data
|
|
1794
|
-
*
|
|
1795
|
-
* @param userId - ID of user to update
|
|
1796
|
-
* @param userData - User data to update
|
|
1797
|
-
* @returns Promise resolving to updated user data
|
|
1798
|
-
*/
|
|
1799
|
-
async updateUser(userId, userData) {
|
|
1800
|
-
return this.userSDK.updateUserAsAdmin(userId, userData);
|
|
1801
|
-
}
|
|
1802
|
-
/**
|
|
1803
|
-
* Admin: Toggle user active status
|
|
1804
|
-
*
|
|
1805
|
-
* @param user - User to toggle status for
|
|
1806
|
-
* @returns Promise resolving to updated user data
|
|
1807
|
-
*/
|
|
1808
|
-
async toggleUserStatus(user) {
|
|
1809
|
-
return this.userSDK.toggleUserActiveStatusByUser(user);
|
|
1810
|
-
}
|
|
1811
|
-
/**
|
|
1812
|
-
* Get the full user SDK for advanced operations
|
|
1813
|
-
*
|
|
1814
|
-
* @returns UserSDK instance
|
|
1815
|
-
*/
|
|
1816
|
-
getUserSDK() {
|
|
1817
|
-
return this.userSDK;
|
|
1818
|
-
}
|
|
1819
|
-
}
|
|
1820
|
-
|
|
1821
|
-
/**
|
|
1822
|
-
* User Status Manager - Clean, high-level interface for user status operations
|
|
1823
|
-
*
|
|
1824
|
-
* Provides a simplified API for common user status management tasks while maintaining
|
|
1825
|
-
* access to the full user status SDK for advanced use cases.
|
|
1826
|
-
*/
|
|
1827
|
-
class UserStatusManager {
|
|
1828
|
-
constructor(apiClient) {
|
|
1829
|
-
this.apiClient = apiClient;
|
|
1830
|
-
this.userStatusSDK = createUserStatusSDK(apiClient);
|
|
1831
|
-
}
|
|
1832
|
-
/**
|
|
1833
|
-
* Get all user status types
|
|
1834
|
-
*
|
|
1835
|
-
* @returns Promise resolving to array of user status types
|
|
1836
|
-
*/
|
|
1837
|
-
async getUserStatusTypes() {
|
|
1838
|
-
return this.userStatusSDK.getRemoteUserStatusTypes();
|
|
1839
|
-
}
|
|
1840
|
-
/**
|
|
1841
|
-
* Get earned user status for authenticated user
|
|
1842
|
-
*
|
|
1843
|
-
* @returns Promise resolving to array of earned user status
|
|
1844
|
-
*/
|
|
1845
|
-
async getEarnedUserStatus() {
|
|
1846
|
-
return this.userStatusSDK.getRemoteEarnedUserStatus();
|
|
1847
|
-
}
|
|
1848
|
-
/**
|
|
1849
|
-
* Admin: Create new user status type
|
|
1850
|
-
*
|
|
1851
|
-
* @param userStatusType - User status type data
|
|
1852
|
-
* @returns Promise resolving to created user status type
|
|
1853
|
-
*/
|
|
1854
|
-
async createUserStatusType(userStatusType) {
|
|
1855
|
-
return this.userStatusSDK.createUserStatusType(userStatusType);
|
|
1856
|
-
}
|
|
1857
|
-
/**
|
|
1858
|
-
* Get the full user status SDK for advanced operations
|
|
1859
|
-
*
|
|
1860
|
-
* @returns UserStatusSDK instance
|
|
1861
|
-
*/
|
|
1862
|
-
getUserStatusSDK() {
|
|
1863
|
-
return this.userStatusSDK;
|
|
1864
|
-
}
|
|
1865
|
-
}
|
|
1866
|
-
|
|
1867
|
-
/**
|
|
1868
|
-
* Token Manager - Clean, high-level interface for token operations
|
|
1869
|
-
*
|
|
1870
|
-
* Provides a simplified API for common token management tasks while maintaining
|
|
1871
|
-
* access to the full token SDK for advanced use cases.
|
|
1872
|
-
*/
|
|
1873
|
-
class TokenManager {
|
|
1874
|
-
constructor(apiClient) {
|
|
1875
|
-
this.apiClient = apiClient;
|
|
1876
|
-
this.tokenSDK = new TokenSDK(apiClient);
|
|
1877
|
-
}
|
|
1878
|
-
/**
|
|
1879
|
-
* Get all available tokens
|
|
1880
|
-
*
|
|
1881
|
-
* @returns Promise resolving to array of tokens
|
|
1882
|
-
*/
|
|
1883
|
-
async getTokens() {
|
|
1884
|
-
return this.tokenSDK.getTokens();
|
|
1885
|
-
}
|
|
1886
|
-
/**
|
|
1887
|
-
* Get all token types
|
|
1888
|
-
*
|
|
1889
|
-
* @returns Promise resolving to token types
|
|
1890
|
-
*/
|
|
1891
|
-
async getTokenTypes() {
|
|
1892
|
-
return this.tokenSDK.getTokenTypes();
|
|
1893
|
-
}
|
|
1894
|
-
/**
|
|
1895
|
-
* Get active credit token
|
|
1896
|
-
*
|
|
1897
|
-
* @returns Promise resolving to active credit token
|
|
1898
|
-
*/
|
|
1899
|
-
async getActiveCreditToken() {
|
|
1900
|
-
return this.tokenSDK.getActiveCreditToken();
|
|
1901
|
-
}
|
|
1902
|
-
/**
|
|
1903
|
-
* Get reward tokens
|
|
1904
|
-
*
|
|
1905
|
-
* @returns Promise resolving to reward tokens
|
|
1906
|
-
*/
|
|
1907
|
-
async getRewardTokens() {
|
|
1908
|
-
return this.tokenSDK.getRewardTokens();
|
|
1909
|
-
}
|
|
1910
|
-
/**
|
|
1911
|
-
* Get status tokens
|
|
1912
|
-
*
|
|
1913
|
-
* @returns Promise resolving to status tokens
|
|
1914
|
-
*/
|
|
1915
|
-
async getStatusTokens() {
|
|
1916
|
-
return this.tokenSDK.getStatusTokens();
|
|
1917
|
-
}
|
|
1918
|
-
/**
|
|
1919
|
-
* Get token by contract address
|
|
1920
|
-
*
|
|
1921
|
-
* @param contractAddress - Contract address to search for
|
|
1922
|
-
* @param contractTokenId - Optional contract token ID
|
|
1923
|
-
* @returns Promise resolving to token
|
|
1924
|
-
*/
|
|
1925
|
-
async getTokenByContract(contractAddress, contractTokenId) {
|
|
1926
|
-
return this.tokenSDK.getTokenByContract(contractAddress, contractTokenId);
|
|
1927
|
-
}
|
|
1928
|
-
/**
|
|
1929
|
-
* Admin: Create new token
|
|
1930
|
-
*
|
|
1931
|
-
* @param tokenData - Token creation data
|
|
1932
|
-
* @returns Promise resolving to created token
|
|
1933
|
-
*/
|
|
1934
|
-
async createToken(tokenData) {
|
|
1935
|
-
return this.tokenSDK.createToken(tokenData);
|
|
1936
|
-
}
|
|
1937
|
-
/**
|
|
1938
|
-
* Admin: Update token
|
|
1939
|
-
*
|
|
1940
|
-
* @param tokenId - Token ID to update
|
|
1941
|
-
* @param tokenData - Token update data
|
|
1942
|
-
* @returns Promise resolving to updated token
|
|
1943
|
-
*/
|
|
1944
|
-
async updateToken(tokenId, tokenData) {
|
|
1945
|
-
return this.tokenSDK.updateToken(tokenId, tokenData);
|
|
1946
|
-
}
|
|
1947
|
-
/**
|
|
1948
|
-
* Admin: Toggle token active status
|
|
1949
|
-
*
|
|
1950
|
-
* @param tokenId - Token ID to toggle
|
|
1951
|
-
* @returns Promise resolving to updated token
|
|
1952
|
-
*/
|
|
1953
|
-
async toggleTokenActive(tokenId) {
|
|
1954
|
-
return this.tokenSDK.toggleTokenActive(tokenId);
|
|
1955
|
-
}
|
|
1956
|
-
/**
|
|
1957
|
-
* Get the full token SDK for advanced operations
|
|
1958
|
-
*
|
|
1959
|
-
* @returns TokenSDK instance
|
|
1960
|
-
*/
|
|
1961
|
-
getTokenSDK() {
|
|
1962
|
-
return this.tokenSDK;
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1965
|
-
|
|
1966
|
-
/**
|
|
1967
|
-
* Business Manager - Clean, high-level interface for business operations
|
|
1968
|
-
*
|
|
1969
|
-
* Provides a simplified API for common business management tasks while maintaining
|
|
1970
|
-
* access to the full business SDK for advanced use cases.
|
|
1971
|
-
*/
|
|
1972
|
-
class BusinessManager {
|
|
1973
|
-
constructor(apiClient) {
|
|
1974
|
-
this.apiClient = apiClient;
|
|
1975
|
-
this.businessSDK = createBusinessSDK(apiClient);
|
|
1976
|
-
}
|
|
1977
|
-
/**
|
|
1978
|
-
* Get all active businesses
|
|
1979
|
-
*
|
|
1980
|
-
* @returns Promise resolving to array of active businesses
|
|
1981
|
-
*/
|
|
1982
|
-
async getActiveBusinesses() {
|
|
1983
|
-
return this.businessSDK.getActiveBusinesses();
|
|
1984
|
-
}
|
|
1985
|
-
/**
|
|
1986
|
-
* Get business by ID
|
|
1987
|
-
*
|
|
1988
|
-
* @param businessId - Business ID to fetch
|
|
1989
|
-
* @returns Promise resolving to business data
|
|
1990
|
-
*/
|
|
1991
|
-
async getBusinessById(businessId) {
|
|
1992
|
-
return this.businessSDK.getBusinessById(businessId);
|
|
1993
|
-
}
|
|
1994
|
-
/**
|
|
1995
|
-
* Get business by account address
|
|
1996
|
-
*
|
|
1997
|
-
* @param accountAddress - Account address to search for
|
|
1998
|
-
* @returns Promise resolving to business data
|
|
1999
|
-
*/
|
|
2000
|
-
async getBusinessByAccount(accountAddress) {
|
|
2001
|
-
return this.businessSDK.getBusinessByAccount(accountAddress);
|
|
2002
|
-
}
|
|
2003
|
-
/**
|
|
2004
|
-
* Get all business types
|
|
2005
|
-
*
|
|
2006
|
-
* @returns Promise resolving to array of business types
|
|
2007
|
-
*/
|
|
2008
|
-
async getBusinessTypes() {
|
|
2009
|
-
return this.businessSDK.getBusinessTypes();
|
|
2010
|
-
}
|
|
2011
|
-
/**
|
|
2012
|
-
* Get businesses by type
|
|
2013
|
-
*
|
|
2014
|
-
* @param typeId - Business type ID to filter by
|
|
2015
|
-
* @returns Promise resolving to array of businesses
|
|
2016
|
-
*/
|
|
2017
|
-
async getBusinessesByType(typeId) {
|
|
2018
|
-
return this.businessSDK.getBusinessesByType(typeId);
|
|
2019
|
-
}
|
|
2020
|
-
/**
|
|
2021
|
-
* Admin: Get all businesses (including inactive)
|
|
2022
|
-
*
|
|
2023
|
-
* @returns Promise resolving to array of all businesses
|
|
2024
|
-
*/
|
|
2025
|
-
async getBusinesses() {
|
|
2026
|
-
return this.businessSDK.getBusinesses();
|
|
2027
|
-
}
|
|
2028
|
-
/**
|
|
2029
|
-
* Admin: Create new business
|
|
2030
|
-
*
|
|
2031
|
-
* @param displayName - Display name for the business
|
|
2032
|
-
* @returns Promise resolving to created business data
|
|
2033
|
-
*/
|
|
2034
|
-
async createBusiness(displayName) {
|
|
2035
|
-
return this.businessSDK.createBusinessByDisplayName(displayName);
|
|
2036
|
-
}
|
|
2037
|
-
/**
|
|
2038
|
-
* Admin: Update business
|
|
2039
|
-
*
|
|
2040
|
-
* @param businessId - ID of business to update
|
|
2041
|
-
* @param businessData - Business data to update
|
|
2042
|
-
* @returns Promise resolving to updated business data
|
|
2043
|
-
*/
|
|
2044
|
-
async updateBusiness(businessId, businessData) {
|
|
2045
|
-
return this.businessSDK.updateBusiness(businessId, businessData);
|
|
2046
|
-
}
|
|
2047
|
-
/**
|
|
2048
|
-
* Admin: Toggle business active status
|
|
2049
|
-
*
|
|
2050
|
-
* @param businessId - ID of business to toggle
|
|
2051
|
-
* @param toggleData - Toggle request data
|
|
2052
|
-
* @returns Promise resolving to updated business data
|
|
2053
|
-
*/
|
|
2054
|
-
async toggleBusinessStatus(businessId, toggleData) {
|
|
2055
|
-
return this.businessSDK.toggleBusinessActive(businessId, toggleData);
|
|
2056
|
-
}
|
|
2057
|
-
/**
|
|
2058
|
-
* Get the full business SDK for advanced operations
|
|
2059
|
-
*
|
|
2060
|
-
* @returns BusinessSDK instance
|
|
2061
|
-
*/
|
|
2062
|
-
getBusinessSDK() {
|
|
2063
|
-
return this.businessSDK;
|
|
2064
|
-
}
|
|
2065
|
-
}
|
|
2066
|
-
|
|
2067
|
-
/**
|
|
2068
|
-
* Campaign Manager - Clean, high-level interface for campaign operations
|
|
2069
|
-
*
|
|
2070
|
-
* Provides a simplified API for common campaign management tasks while maintaining
|
|
2071
|
-
* access to the full campaign SDK for advanced use cases.
|
|
2072
|
-
*/
|
|
2073
|
-
class CampaignManager {
|
|
2074
|
-
constructor(apiClient) {
|
|
2075
|
-
this.apiClient = apiClient;
|
|
2076
|
-
this.campaignSDK = createCampaignSDK(apiClient);
|
|
2077
|
-
}
|
|
2078
|
-
/**
|
|
2079
|
-
* Get all active campaigns
|
|
2080
|
-
*
|
|
2081
|
-
* @returns Promise resolving to array of active campaigns
|
|
2082
|
-
*/
|
|
2083
|
-
async getActiveCampaigns() {
|
|
2084
|
-
return this.campaignSDK.getActiveCampaigns();
|
|
2085
|
-
}
|
|
2086
|
-
/**
|
|
2087
|
-
* Get campaign by ID
|
|
2088
|
-
*
|
|
2089
|
-
* @param campaignId - ID of the campaign
|
|
2090
|
-
* @returns Promise resolving to campaign data
|
|
2091
|
-
*/
|
|
2092
|
-
async getCampaignById(campaignId) {
|
|
2093
|
-
return this.campaignSDK.getCampaignById(campaignId);
|
|
2094
|
-
}
|
|
2095
|
-
/**
|
|
2096
|
-
* Claim a campaign reward
|
|
2097
|
-
*
|
|
2098
|
-
* @param claimRequest - Campaign claim data
|
|
2099
|
-
* @returns Promise resolving to claim result
|
|
2100
|
-
*/
|
|
2101
|
-
async claimCampaign(claimRequest) {
|
|
2102
|
-
return this.campaignSDK.claimCampaign(claimRequest);
|
|
2103
|
-
}
|
|
2104
|
-
/**
|
|
2105
|
-
* Get user's campaign claims
|
|
2106
|
-
*
|
|
2107
|
-
* @returns Promise resolving to array of user's claims
|
|
2108
|
-
*/
|
|
2109
|
-
async getUserClaims() {
|
|
2110
|
-
return this.campaignSDK.getClaimsForLoggedUser();
|
|
2111
|
-
}
|
|
2112
|
-
/**
|
|
2113
|
-
* Admin: Get all campaigns
|
|
2114
|
-
*
|
|
2115
|
-
* @param active - Filter by active status
|
|
2116
|
-
* @returns Promise resolving to array of campaigns
|
|
2117
|
-
*/
|
|
2118
|
-
async getAllCampaigns(active) {
|
|
2119
|
-
return this.campaignSDK.getCampaigns(active);
|
|
2120
|
-
}
|
|
2121
|
-
/**
|
|
2122
|
-
* Admin: Create new campaign
|
|
2123
|
-
*
|
|
2124
|
-
* @param campaignData - Campaign data
|
|
2125
|
-
* @returns Promise resolving to created campaign
|
|
2126
|
-
*/
|
|
2127
|
-
async createCampaign(campaignData) {
|
|
2128
|
-
return this.campaignSDK.createCampaign(campaignData);
|
|
2129
|
-
}
|
|
2130
|
-
/**
|
|
2131
|
-
* Admin: Update campaign
|
|
2132
|
-
*
|
|
2133
|
-
* @param campaignId - ID of campaign to update
|
|
2134
|
-
* @param campaignData - Updated campaign data
|
|
2135
|
-
* @returns Promise resolving to updated campaign
|
|
2136
|
-
*/
|
|
2137
|
-
async updateCampaign(campaignId, campaignData) {
|
|
2138
|
-
return this.campaignSDK.updateCampaign(campaignId, campaignData);
|
|
2139
|
-
}
|
|
2140
|
-
/**
|
|
2141
|
-
* Admin: Toggle campaign active status
|
|
2142
|
-
*
|
|
2143
|
-
* @param campaignId - ID of campaign to toggle
|
|
2144
|
-
* @returns Promise resolving to updated campaign
|
|
2145
|
-
*/
|
|
2146
|
-
async toggleCampaignStatus(campaignId) {
|
|
2147
|
-
return this.campaignSDK.toggleCampaignActive(campaignId);
|
|
2148
|
-
}
|
|
2149
|
-
/**
|
|
2150
|
-
* Admin: Toggle campaign testnet environment
|
|
2151
|
-
*
|
|
2152
|
-
* @param campaignId - ID of campaign to toggle
|
|
2153
|
-
* @returns Promise resolving to updated campaign
|
|
2154
|
-
*/
|
|
2155
|
-
async toggleCampaignTestnet(campaignId) {
|
|
2156
|
-
return this.campaignSDK.toggleCampaignTestnet(campaignId);
|
|
2157
|
-
}
|
|
2158
|
-
/**
|
|
2159
|
-
* Admin: Get campaign triggers
|
|
2160
|
-
*
|
|
2161
|
-
* @returns Promise resolving to array of campaign triggers
|
|
2162
|
-
*/
|
|
2163
|
-
async getCampaignTriggers() {
|
|
2164
|
-
return this.campaignSDK.getCampaignTriggers();
|
|
2165
|
-
}
|
|
2166
|
-
/**
|
|
2167
|
-
* Admin: Set campaign trigger
|
|
2168
|
-
*
|
|
2169
|
-
* @param campaignId - ID of campaign
|
|
2170
|
-
* @param triggerId - ID of trigger to set
|
|
2171
|
-
* @returns Promise resolving to updated campaign
|
|
2172
|
-
*/
|
|
2173
|
-
async setCampaignTrigger(campaignId, triggerId) {
|
|
2174
|
-
return this.campaignSDK.setCampaignTrigger(campaignId, triggerId);
|
|
2175
|
-
}
|
|
2176
|
-
/**
|
|
2177
|
-
* Admin: Create campaign token unit
|
|
2178
|
-
*
|
|
2179
|
-
* @param campaignId - ID of campaign
|
|
2180
|
-
* @param tokenUnit - Token unit data
|
|
2181
|
-
* @returns Promise resolving to updated campaign
|
|
2182
|
-
*/
|
|
2183
|
-
async createCampaignTokenUnit(campaignId, tokenUnit) {
|
|
2184
|
-
return this.campaignSDK.createCampaignTokenUnit(campaignId, tokenUnit);
|
|
2185
|
-
}
|
|
2186
|
-
/**
|
|
2187
|
-
* Admin: Delete campaign token unit
|
|
2188
|
-
*
|
|
2189
|
-
* @param campaignId - ID of campaign
|
|
2190
|
-
* @param tokenUnitId - ID of token unit to delete
|
|
2191
|
-
* @returns Promise resolving to updated campaign
|
|
2192
|
-
*/
|
|
2193
|
-
async deleteCampaignTokenUnit(campaignId, tokenUnitId) {
|
|
2194
|
-
return this.campaignSDK.deleteCampaignTokenUnit(campaignId, tokenUnitId);
|
|
2195
|
-
}
|
|
2196
|
-
/**
|
|
2197
|
-
* Admin: Add business engagement to campaign
|
|
2198
|
-
*
|
|
2199
|
-
* @param campaignId - ID of campaign
|
|
2200
|
-
* @param engagement - Business engagement data
|
|
2201
|
-
* @returns Promise resolving to updated campaign
|
|
2202
|
-
*/
|
|
2203
|
-
async addBusinessEngagementToCampaign(campaignId, engagement) {
|
|
2204
|
-
return this.campaignSDK.addBusinessEngagementToCampaign(campaignId, engagement);
|
|
2205
|
-
}
|
|
2206
|
-
/**
|
|
2207
|
-
* Admin: Update campaign business engagement
|
|
2208
|
-
*
|
|
2209
|
-
* @param campaignId - ID of campaign
|
|
2210
|
-
* @param engagementId - ID of engagement to update
|
|
2211
|
-
* @param engagement - Updated engagement data
|
|
2212
|
-
* @returns Promise resolving to updated campaign
|
|
2213
|
-
*/
|
|
2214
|
-
async updateCampaignBusinessEngagement(campaignId, engagementId, engagement) {
|
|
2215
|
-
return this.campaignSDK.updateCampaignBusinessEngagement(campaignId, engagementId, engagement);
|
|
2216
|
-
}
|
|
2217
|
-
/**
|
|
2218
|
-
* Admin: Delete campaign business engagement
|
|
2219
|
-
*
|
|
2220
|
-
* @param campaignId - ID of campaign
|
|
2221
|
-
* @param engagementId - ID of engagement to delete
|
|
2222
|
-
* @returns Promise resolving to updated campaign
|
|
2223
|
-
*/
|
|
2224
|
-
async deleteCampaignBusinessEngagement(campaignId, engagementId) {
|
|
2225
|
-
return this.campaignSDK.deleteCampaignBusinessEngagement(campaignId, engagementId);
|
|
2226
|
-
}
|
|
2227
|
-
/**
|
|
2228
|
-
* Admin: Get all campaign claims
|
|
2229
|
-
*
|
|
2230
|
-
* @returns Promise resolving to array of campaign claims
|
|
2231
|
-
*/
|
|
2232
|
-
async getCampaignClaims() {
|
|
2233
|
-
return this.campaignSDK.getCampaignClaims();
|
|
2234
|
-
}
|
|
2235
|
-
/**
|
|
2236
|
-
* Admin: Get campaign claims by user ID
|
|
2237
|
-
*
|
|
2238
|
-
* @param userId - ID of user
|
|
2239
|
-
* @returns Promise resolving to array of user's campaign claims
|
|
2240
|
-
*/
|
|
2241
|
-
async getCampaignClaimsByUserId(userId) {
|
|
2242
|
-
return this.campaignSDK.getCampaignClaimsByUserId(userId);
|
|
2243
|
-
}
|
|
2244
|
-
/**
|
|
2245
|
-
* Admin: Get campaign claims by business ID
|
|
2246
|
-
*
|
|
2247
|
-
* @param businessId - ID of business
|
|
2248
|
-
* @returns Promise resolving to array of business's campaign claims
|
|
2249
|
-
*/
|
|
2250
|
-
async getCampaignClaimsByBusinessId(businessId) {
|
|
2251
|
-
return this.campaignSDK.getCampaignClaimsByBusinessId(businessId);
|
|
2252
|
-
}
|
|
2253
|
-
/**
|
|
2254
|
-
* Get the full campaign SDK for advanced operations
|
|
2255
|
-
*
|
|
2256
|
-
* @returns CampaignSDK instance
|
|
2257
|
-
*/
|
|
2258
|
-
getCampaignSDK() {
|
|
2259
|
-
return this.campaignSDK;
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
|
|
2263
|
-
/**
|
|
2264
|
-
* Redemption Manager - Clean, high-level interface for redemption operations
|
|
2265
|
-
*
|
|
2266
|
-
* Provides a simplified API for common redemption management tasks while maintaining
|
|
2267
|
-
* access to the full redemption SDK for advanced use cases.
|
|
2268
|
-
*/
|
|
2269
|
-
class RedemptionManager {
|
|
2270
|
-
constructor(apiClient) {
|
|
2271
|
-
this.apiClient = apiClient;
|
|
2272
|
-
this.redemptionSDK = createRedemptionSDK(apiClient);
|
|
2273
|
-
}
|
|
2274
|
-
/**
|
|
2275
|
-
* Get all active redemption offers
|
|
2276
|
-
*
|
|
2277
|
-
* @returns Promise resolving to array of active redemptions
|
|
2278
|
-
*/
|
|
2279
|
-
async getActiveRedemptions() {
|
|
2280
|
-
return this.redemptionSDK.getActiveRedemptions();
|
|
2281
|
-
}
|
|
2282
|
-
/**
|
|
2283
|
-
* Get available redemption types
|
|
2284
|
-
*
|
|
2285
|
-
* @returns Promise resolving to array of redemption types
|
|
2286
|
-
*/
|
|
2287
|
-
async getRedemptionTypes() {
|
|
2288
|
-
return this.redemptionSDK.getRedemptionTypes();
|
|
2289
|
-
}
|
|
2290
|
-
/**
|
|
2291
|
-
* Redeem a redemption offer
|
|
2292
|
-
*
|
|
2293
|
-
* @param redemptionId - ID of the redemption to redeem
|
|
2294
|
-
* @returns Promise resolving to redemption result
|
|
2295
|
-
*/
|
|
2296
|
-
async redeemOffer(redemptionId) {
|
|
2297
|
-
return this.redemptionSDK.redeemRedemption(redemptionId);
|
|
2298
|
-
}
|
|
2299
|
-
/**
|
|
2300
|
-
* Get user's redemption history
|
|
2301
|
-
*
|
|
2302
|
-
* @returns Promise resolving to array of user's redemptions
|
|
2303
|
-
*/
|
|
2304
|
-
async getUserRedemptions() {
|
|
2305
|
-
return this.redemptionSDK.getUserRedeems();
|
|
2306
|
-
}
|
|
2307
|
-
/**
|
|
2308
|
-
* Admin: Get all redemptions
|
|
2309
|
-
*
|
|
2310
|
-
* @param active - Filter by active status
|
|
2311
|
-
* @returns Promise resolving to array of redemptions
|
|
2312
|
-
*/
|
|
2313
|
-
async getAllRedemptions(active) {
|
|
2314
|
-
return this.redemptionSDK.getRedemptionsAsAdmin(active);
|
|
2315
|
-
}
|
|
2316
|
-
/**
|
|
2317
|
-
* Admin: Create new redemption offer
|
|
2318
|
-
*
|
|
2319
|
-
* @param redemptionData - Redemption data
|
|
2320
|
-
* @returns Promise resolving to created redemption
|
|
2321
|
-
*/
|
|
2322
|
-
async createRedemption(redemptionData) {
|
|
2323
|
-
return this.redemptionSDK.createRedemption(redemptionData);
|
|
2324
|
-
}
|
|
2325
|
-
/**
|
|
2326
|
-
* Admin: Update redemption
|
|
2327
|
-
*
|
|
2328
|
-
* @param redemptionId - ID of redemption to update
|
|
2329
|
-
* @param redemptionData - Updated redemption data
|
|
2330
|
-
* @returns Promise resolving to updated redemption
|
|
2331
|
-
*/
|
|
2332
|
-
async updateRedemption(redemptionId, redemptionData) {
|
|
2333
|
-
return this.redemptionSDK.updateRedemption(redemptionId, redemptionData);
|
|
2334
|
-
}
|
|
2335
|
-
/**
|
|
2336
|
-
* Admin: Toggle redemption active status
|
|
2337
|
-
*
|
|
2338
|
-
* @param redemptionId - ID of redemption to toggle
|
|
2339
|
-
* @returns Promise resolving to updated redemption
|
|
2340
|
-
*/
|
|
2341
|
-
async toggleRedemptionStatus(redemptionId) {
|
|
2342
|
-
return this.redemptionSDK.toggleRedemptionActive(redemptionId);
|
|
2343
|
-
}
|
|
2344
|
-
/**
|
|
2345
|
-
* Admin: Create redemption token unit
|
|
2346
|
-
*
|
|
2347
|
-
* @param redemptionId - ID of redemption
|
|
2348
|
-
* @param tokenUnit - Token unit data
|
|
2349
|
-
* @returns Promise resolving to updated redemption
|
|
2350
|
-
*/
|
|
2351
|
-
async createRedemptionTokenUnit(redemptionId, tokenUnit) {
|
|
2352
|
-
return this.redemptionSDK.createRedemptionTokenUnit(redemptionId, tokenUnit);
|
|
2353
|
-
}
|
|
2354
|
-
/**
|
|
2355
|
-
* Admin: Delete redemption token unit
|
|
2356
|
-
*
|
|
2357
|
-
* @param redemptionId - ID of redemption
|
|
2358
|
-
* @param tokenUnitId - ID of token unit to delete
|
|
2359
|
-
* @returns Promise resolving to updated redemption
|
|
2360
|
-
*/
|
|
2361
|
-
async deleteRedemptionTokenUnit(redemptionId, tokenUnitId) {
|
|
2362
|
-
return this.redemptionSDK.deleteRedemptionTokenUnit(redemptionId, tokenUnitId);
|
|
2363
|
-
}
|
|
2364
|
-
/**
|
|
2365
|
-
* Get the full redemption SDK for advanced operations
|
|
2366
|
-
*
|
|
2367
|
-
* @returns RedemptionSDK instance
|
|
2368
|
-
*/
|
|
2369
|
-
getRedemptionSDK() {
|
|
2370
|
-
return this.redemptionSDK;
|
|
2371
|
-
}
|
|
2372
|
-
}
|
|
2373
|
-
|
|
2374
|
-
/**
|
|
2375
|
-
* Transaction Manager - Clean, high-level interface for transaction operations
|
|
2376
|
-
*
|
|
2377
|
-
* Provides a simplified API for common transaction management tasks while maintaining
|
|
2378
|
-
* access to the full transaction SDK for advanced use cases.
|
|
2379
|
-
*/
|
|
2380
|
-
class TransactionManager {
|
|
2381
|
-
constructor(apiClient) {
|
|
2382
|
-
this.apiClient = apiClient;
|
|
2383
|
-
this.transactionSDK = createTransactionSDK(apiClient);
|
|
2384
|
-
}
|
|
2385
|
-
/**
|
|
2386
|
-
* Get transaction by ID
|
|
2387
|
-
*
|
|
2388
|
-
* @param transactionId - ID of the transaction
|
|
2389
|
-
* @returns Promise resolving to transaction data
|
|
2390
|
-
*/
|
|
2391
|
-
async getTransactionById(transactionId) {
|
|
2392
|
-
return this.transactionSDK.getTransactionById(transactionId);
|
|
2393
|
-
}
|
|
2394
|
-
/**
|
|
2395
|
-
* Create a new transaction
|
|
2396
|
-
*
|
|
2397
|
-
* @param transactionData - Transaction data
|
|
2398
|
-
* @returns Promise resolving to transaction response
|
|
2399
|
-
*/
|
|
2400
|
-
async createTransaction(transactionData) {
|
|
2401
|
-
return this.transactionSDK.createTransaction(transactionData);
|
|
2402
|
-
}
|
|
2403
|
-
/**
|
|
2404
|
-
* Get user's transaction history
|
|
2405
|
-
*
|
|
2406
|
-
* @param type - Transaction type filter
|
|
2407
|
-
* @returns Promise resolving to array of user's transactions
|
|
2408
|
-
*/
|
|
2409
|
-
async getUserTransactionHistory(type) {
|
|
2410
|
-
return this.transactionSDK.getUserTransactionHistory(type);
|
|
2411
|
-
}
|
|
2412
|
-
/**
|
|
2413
|
-
* Admin: Get all tenant transactions
|
|
2414
|
-
*
|
|
2415
|
-
* @returns Promise resolving to array of tenant transactions
|
|
2416
|
-
*/
|
|
2417
|
-
async getTenantTransactions() {
|
|
2418
|
-
return this.transactionSDK.getTenantTransactions();
|
|
2419
|
-
}
|
|
2420
|
-
/**
|
|
2421
|
-
* Admin: Get paginated transactions
|
|
2422
|
-
*
|
|
2423
|
-
* @param params - Pagination parameters
|
|
2424
|
-
* @returns Promise resolving to paginated transaction results
|
|
2425
|
-
*/
|
|
2426
|
-
async getPaginatedTransactions(params) {
|
|
2427
|
-
return this.transactionSDK.getPaginatedTransactions(params);
|
|
2428
|
-
}
|
|
2429
|
-
/**
|
|
2430
|
-
* Admin: Export transactions as CSV
|
|
2431
|
-
*
|
|
2432
|
-
* @returns Promise resolving to CSV blob
|
|
2433
|
-
*/
|
|
2434
|
-
async exportTransactionsCSV() {
|
|
2435
|
-
return this.transactionSDK.exportTransactionsCSV();
|
|
2436
|
-
}
|
|
2437
|
-
/**
|
|
2438
|
-
* Get the full transaction SDK for advanced operations
|
|
2439
|
-
*
|
|
2440
|
-
* @returns TransactionSDK instance
|
|
2441
|
-
*/
|
|
2442
|
-
getTransactionSDK() {
|
|
2443
|
-
return this.transactionSDK;
|
|
2444
|
-
}
|
|
2445
|
-
}
|
|
2446
|
-
|
|
2447
|
-
/**
|
|
2448
|
-
* Purchase Manager - Clean, high-level interface for purchase operations
|
|
2449
|
-
*
|
|
2450
|
-
* Provides a simplified API for common purchase management tasks while maintaining
|
|
2451
|
-
* access to the full payment SDK for advanced use cases.
|
|
2452
|
-
*/
|
|
2453
|
-
class PurchaseManager {
|
|
2454
|
-
constructor(apiClient) {
|
|
2455
|
-
this.apiClient = apiClient;
|
|
2456
|
-
this.paymentSDK = createPaymentSDK(apiClient);
|
|
2457
|
-
}
|
|
2458
|
-
/**
|
|
2459
|
-
* Create a payment intent
|
|
2460
|
-
*
|
|
2461
|
-
* @param amount - Payment amount
|
|
2462
|
-
* @param currency - Payment currency
|
|
2463
|
-
* @param receiptEmail - Receipt email
|
|
2464
|
-
* @param description - Payment description
|
|
2465
|
-
* @returns Promise resolving to created payment intent
|
|
2466
|
-
*/
|
|
2467
|
-
async createPaymentIntent(amount, currency, receiptEmail, description) {
|
|
2468
|
-
return this.paymentSDK.createPaymentIntent(amount, currency, receiptEmail, description);
|
|
2469
|
-
}
|
|
2470
|
-
/**
|
|
2471
|
-
* Get active purchase tokens
|
|
2472
|
-
*
|
|
2473
|
-
* @param active - Filter by active status
|
|
2474
|
-
* @returns Promise resolving to purchase tokens
|
|
2475
|
-
*/
|
|
2476
|
-
async getActivePurchaseTokens(active) {
|
|
2477
|
-
return this.paymentSDK.getActivePurchaseTokens(active);
|
|
2478
|
-
}
|
|
2479
|
-
/**
|
|
2480
|
-
* Get all user purchases
|
|
2481
|
-
*
|
|
2482
|
-
* @returns Promise resolving to array of user's purchases
|
|
2483
|
-
*/
|
|
2484
|
-
async getAllUserPurchases() {
|
|
2485
|
-
return this.paymentSDK.getAllUserPurchases();
|
|
2486
|
-
}
|
|
2487
|
-
/**
|
|
2488
|
-
* Get the full purchase SDK for advanced operations
|
|
2489
|
-
*
|
|
2490
|
-
* @returns PaymentSDK instance
|
|
2491
|
-
*/
|
|
2492
|
-
getPurchaseSDK() {
|
|
2493
|
-
return this.paymentSDK;
|
|
2494
|
-
}
|
|
2495
|
-
}
|
|
2496
|
-
|
|
2497
|
-
/**
|
|
2498
|
-
* Platform-Agnostic File API Client
|
|
2499
|
-
*
|
|
2500
|
-
* Handles file operations using the PERS backend's RESTful endpoints.
|
|
2501
|
-
*/
|
|
2502
|
-
class FileApi {
|
|
2503
|
-
constructor(apiClient) {
|
|
2504
|
-
this.apiClient = apiClient;
|
|
2505
|
-
this.basePath = '/files';
|
|
2506
|
-
}
|
|
2507
|
-
// ==========================================
|
|
2508
|
-
// PUBLIC OPERATIONS
|
|
2509
|
-
// ==========================================
|
|
2510
|
-
/**
|
|
2511
|
-
* PUBLIC: Get signed URL for file operations
|
|
2512
|
-
*
|
|
2513
|
-
* @param request - Signed URL request parameters
|
|
2514
|
-
* @returns Promise resolving to signed URL response
|
|
2515
|
-
*/
|
|
2516
|
-
async getSignedUrl(request) {
|
|
2517
|
-
return this.apiClient.post(`${this.basePath}/entity-storage-url`, request);
|
|
2518
|
-
}
|
|
2519
|
-
/**
|
|
2520
|
-
* PUBLIC: Get signed GET URL for file access
|
|
2521
|
-
*
|
|
2522
|
-
* @param url - File URL
|
|
2523
|
-
* @param expireSeconds - Optional expiration time in seconds
|
|
2524
|
-
* @returns Promise resolving to signed URL response
|
|
2525
|
-
*/
|
|
2526
|
-
async getSignedGetUrl(url, expireSeconds) {
|
|
2527
|
-
const searchParams = new URLSearchParams({ url });
|
|
2528
|
-
if (expireSeconds) {
|
|
2529
|
-
searchParams.set('expireSeconds', expireSeconds.toString());
|
|
2530
|
-
}
|
|
2531
|
-
return this.apiClient.get(`${this.basePath}/signed-url?${searchParams.toString()}`);
|
|
2532
|
-
}
|
|
2533
|
-
/**
|
|
2534
|
-
* PUBLIC: Optimize media from URL
|
|
2535
|
-
*
|
|
2536
|
-
* @param request - File optimization request
|
|
2537
|
-
* @returns Promise resolving to optimized file URL
|
|
2538
|
-
*/
|
|
2539
|
-
async optimizeMediaFromUrl(request) {
|
|
2540
|
-
const searchParams = new URLSearchParams({ url: request.url });
|
|
2541
|
-
if (request.width)
|
|
2542
|
-
searchParams.set('width', request.width.toString());
|
|
2543
|
-
if (request.height)
|
|
2544
|
-
searchParams.set('height', request.height.toString());
|
|
2545
|
-
return this.apiClient.get(`/file/optimize-url?${searchParams.toString()}`);
|
|
2546
|
-
}
|
|
2547
|
-
}
|
|
2548
|
-
|
|
2549
|
-
/**
|
|
2550
|
-
* File Service - High-level file operations
|
|
2551
|
-
*
|
|
2552
|
-
* Provides convenient methods for file upload, signed URLs, and media optimization.
|
|
2553
|
-
*/
|
|
2554
|
-
class FileService {
|
|
2555
|
-
constructor(apiClient) {
|
|
2556
|
-
this.fileApi = new FileApi(apiClient);
|
|
2557
|
-
}
|
|
2558
|
-
/**
|
|
2559
|
-
* Get signed PUT URL for file upload
|
|
2560
|
-
*
|
|
2561
|
-
* @param entityId - Entity ID to associate the file with
|
|
2562
|
-
* @param entityType - Type of entity (token, campaign, etc.)
|
|
2563
|
-
* @param fileExtension - File extension (e.g., 'jpg', 'png')
|
|
2564
|
-
* @returns Promise resolving to signed upload URL
|
|
2565
|
-
*/
|
|
2566
|
-
async getSignedPutUrl(entityId, entityType, fileExtension) {
|
|
2567
|
-
const request = {
|
|
2568
|
-
entityId,
|
|
2569
|
-
entityType,
|
|
2570
|
-
signedUrlType: 'PUT',
|
|
2571
|
-
fileExtension
|
|
2572
|
-
};
|
|
2573
|
-
const response = await this.fileApi.getSignedUrl(request);
|
|
2574
|
-
return response.signedUrl;
|
|
2575
|
-
}
|
|
2576
|
-
/**
|
|
2577
|
-
* Get signed GET URL for file access
|
|
2578
|
-
*
|
|
2579
|
-
* @param entityId - Entity ID
|
|
2580
|
-
* @param entityType - Type of entity
|
|
2581
|
-
* @param expireSeconds - Optional expiration time in seconds
|
|
2582
|
-
* @returns Promise resolving to signed access URL
|
|
2583
|
-
*/
|
|
2584
|
-
async getSignedGetUrl(entityId, entityType, expireSeconds) {
|
|
2585
|
-
const request = {
|
|
2586
|
-
entityId,
|
|
2587
|
-
entityType,
|
|
2588
|
-
signedUrlType: 'GET'
|
|
2589
|
-
};
|
|
2590
|
-
const response = await this.fileApi.getSignedUrl(request);
|
|
2591
|
-
return response.signedUrl;
|
|
2592
|
-
}
|
|
2593
|
-
/**
|
|
2594
|
-
* Get signed URL for any file operation
|
|
2595
|
-
*
|
|
2596
|
-
* @param request - Signed URL request
|
|
2597
|
-
* @returns Promise resolving to signed URL
|
|
2598
|
-
*/
|
|
2599
|
-
async getSignedUrl(request) {
|
|
2600
|
-
const response = await this.fileApi.getSignedUrl(request);
|
|
2601
|
-
return response.signedUrl;
|
|
2602
|
-
}
|
|
2603
|
-
/**
|
|
2604
|
-
* Optimize media from URL
|
|
2605
|
-
*
|
|
2606
|
-
* @param url - Original file URL
|
|
2607
|
-
* @param width - Optional target width
|
|
2608
|
-
* @param height - Optional target height
|
|
2609
|
-
* @returns Promise resolving to optimized file URL
|
|
2610
|
-
*/
|
|
2611
|
-
async optimizeMedia(url, width, height) {
|
|
2612
|
-
const request = { url, width, height };
|
|
2613
|
-
const response = await this.fileApi.optimizeMediaFromUrl(request);
|
|
2614
|
-
return response.optimizedUrl;
|
|
2615
|
-
}
|
|
2616
|
-
/**
|
|
2617
|
-
* Get the file API instance for advanced operations
|
|
2618
|
-
*
|
|
2619
|
-
* @returns FileApi instance
|
|
2620
|
-
*/
|
|
2621
|
-
getFileApi() {
|
|
2622
|
-
return this.fileApi;
|
|
2623
|
-
}
|
|
2624
|
-
}
|
|
2625
|
-
/**
|
|
2626
|
-
* Factory function for creating file service
|
|
2627
|
-
*/
|
|
2628
|
-
function createFileSDK(apiClient) {
|
|
2629
|
-
return new FileService(apiClient);
|
|
2630
|
-
}
|
|
2631
|
-
|
|
2632
|
-
/**
|
|
2633
|
-
* File Manager - Clean, high-level interface for file operations
|
|
2634
|
-
*
|
|
2635
|
-
* Provides a simplified API for common file management tasks while maintaining
|
|
2636
|
-
* access to the full file SDK for advanced use cases.
|
|
2637
|
-
*/
|
|
2638
|
-
class FileManager {
|
|
2639
|
-
constructor(apiClient) {
|
|
2640
|
-
this.apiClient = apiClient;
|
|
2641
|
-
this.fileSDK = createFileSDK(apiClient);
|
|
2642
|
-
}
|
|
2643
|
-
/**
|
|
2644
|
-
* Get signed URL for file upload
|
|
2645
|
-
*
|
|
2646
|
-
* @param entityId - Entity ID to associate the file with
|
|
2647
|
-
* @param entityType - Type of entity (token, campaign, etc.)
|
|
2648
|
-
* @param fileExtension - File extension (e.g., 'jpg', 'png')
|
|
2649
|
-
* @returns Promise resolving to signed upload URL
|
|
2650
|
-
*/
|
|
2651
|
-
async getSignedPutUrl(entityId, entityType, fileExtension) {
|
|
2652
|
-
return this.fileSDK.getSignedPutUrl(entityId, entityType, fileExtension);
|
|
2653
|
-
}
|
|
2654
|
-
/**
|
|
2655
|
-
* Get signed URL for file access
|
|
2656
|
-
*
|
|
2657
|
-
* @param entityId - Entity ID
|
|
2658
|
-
* @param entityType - Type of entity
|
|
2659
|
-
* @param expireSeconds - Optional expiration time in seconds
|
|
2660
|
-
* @returns Promise resolving to signed access URL
|
|
2661
|
-
*/
|
|
2662
|
-
async getSignedGetUrl(entityId, entityType, expireSeconds) {
|
|
2663
|
-
return this.fileSDK.getSignedGetUrl(entityId, entityType, expireSeconds);
|
|
2664
|
-
}
|
|
2665
|
-
/**
|
|
2666
|
-
* Get signed URL for any file operation
|
|
2667
|
-
*
|
|
2668
|
-
* @param request - Signed URL request
|
|
2669
|
-
* @returns Promise resolving to signed URL
|
|
2670
|
-
*/
|
|
2671
|
-
async getSignedUrl(request) {
|
|
2672
|
-
return this.fileSDK.getSignedUrl(request);
|
|
2673
|
-
}
|
|
2674
|
-
/**
|
|
2675
|
-
* Optimize media file
|
|
2676
|
-
*
|
|
2677
|
-
* @param url - Original file URL
|
|
2678
|
-
* @param width - Optional target width
|
|
2679
|
-
* @param height - Optional target height
|
|
2680
|
-
* @returns Promise resolving to optimized file URL
|
|
2681
|
-
*/
|
|
2682
|
-
async optimizeMedia(url, width, height) {
|
|
2683
|
-
return this.fileSDK.optimizeMedia(url, width, height);
|
|
2684
|
-
}
|
|
2685
|
-
/**
|
|
2686
|
-
* Get the full file SDK for advanced operations
|
|
2687
|
-
*
|
|
2688
|
-
* @returns FileService instance
|
|
2689
|
-
*/
|
|
2690
|
-
getFileSDK() {
|
|
2691
|
-
return this.fileSDK;
|
|
2692
|
-
}
|
|
2693
|
-
}
|
|
2694
|
-
|
|
2695
|
-
/**
|
|
2696
|
-
* Tenant Manager - Clean, high-level interface for tenant operations
|
|
2697
|
-
*
|
|
2698
|
-
* Provides a simplified API for common tenant management tasks while maintaining
|
|
2699
|
-
* access to the full tenant SDK for advanced use cases.
|
|
2700
|
-
*/
|
|
2701
|
-
class TenantManager {
|
|
2702
|
-
constructor(apiClient) {
|
|
2703
|
-
this.apiClient = apiClient;
|
|
2704
|
-
this.tenantSDK = createTenantSDK(apiClient);
|
|
2705
|
-
}
|
|
2706
|
-
/**
|
|
2707
|
-
* Get current tenant information
|
|
2708
|
-
*
|
|
2709
|
-
* @returns Promise resolving to tenant data
|
|
2710
|
-
*/
|
|
2711
|
-
async getTenantInfo() {
|
|
2712
|
-
return this.tenantSDK.getRemoteTenant();
|
|
2713
|
-
}
|
|
2714
|
-
/**
|
|
2715
|
-
* Get tenant login token
|
|
2716
|
-
*
|
|
2717
|
-
* @returns Promise resolving to login token
|
|
2718
|
-
*/
|
|
2719
|
-
async getLoginToken() {
|
|
2720
|
-
return this.tenantSDK.getRemoteLoginToken();
|
|
2721
|
-
}
|
|
2722
|
-
/**
|
|
2723
|
-
* Get tenant client configuration
|
|
2724
|
-
*
|
|
2725
|
-
* @returns Promise resolving to client config
|
|
2726
|
-
*/
|
|
2727
|
-
async getClientConfig() {
|
|
2728
|
-
return this.tenantSDK.getRemoteClientConfig();
|
|
2729
|
-
}
|
|
2730
|
-
/**
|
|
2731
|
-
* Admin: Update tenant data
|
|
2732
|
-
*
|
|
2733
|
-
* @param tenantData - Updated tenant data
|
|
2734
|
-
* @returns Promise resolving to updated tenant
|
|
2735
|
-
*/
|
|
2736
|
-
async updateTenant(tenantData) {
|
|
2737
|
-
return this.tenantSDK.updateRemoteTenant(tenantData);
|
|
2738
|
-
}
|
|
2739
|
-
/**
|
|
2740
|
-
* Admin: Get all admins
|
|
2741
|
-
*
|
|
2742
|
-
* @returns Promise resolving to array of admins
|
|
2743
|
-
*/
|
|
2744
|
-
async getAdmins() {
|
|
2745
|
-
return this.tenantSDK.getAdmins();
|
|
2746
|
-
}
|
|
2747
|
-
/**
|
|
2748
|
-
* Admin: Create new admin
|
|
2749
|
-
*
|
|
2750
|
-
* @param adminData - Admin data
|
|
2751
|
-
* @returns Promise resolving to created admin
|
|
2752
|
-
*/
|
|
2753
|
-
async createAdmin(adminData) {
|
|
2754
|
-
return this.tenantSDK.postAdmin(adminData);
|
|
2755
|
-
}
|
|
2756
|
-
/**
|
|
2757
|
-
* Admin: Update existing admin
|
|
2758
|
-
*
|
|
2759
|
-
* @param adminId - ID of the admin to update
|
|
2760
|
-
* @param adminData - Updated admin data
|
|
2761
|
-
* @returns Promise resolving to updated admin
|
|
2762
|
-
*/
|
|
2763
|
-
async updateAdmin(adminId, adminData) {
|
|
2764
|
-
return this.tenantSDK.putAdmin(adminId, adminData);
|
|
2765
|
-
}
|
|
2766
|
-
/**
|
|
2767
|
-
* Get the full tenant SDK for advanced operations
|
|
2768
|
-
*
|
|
2769
|
-
* @returns TenantSDK instance
|
|
2770
|
-
*/
|
|
2771
|
-
getTenantSDK() {
|
|
2772
|
-
return this.tenantSDK;
|
|
2773
|
-
}
|
|
2774
|
-
}
|
|
2775
|
-
|
|
2776
|
-
/**
|
|
2777
|
-
* Analytics Manager - Clean, high-level interface for analytics operations
|
|
2778
|
-
*
|
|
2779
|
-
* Provides a simplified API for common analytics tasks while maintaining
|
|
2780
|
-
* access to the full analytics SDK for advanced use cases.
|
|
2781
|
-
*/
|
|
2782
|
-
class AnalyticsManager {
|
|
2783
|
-
constructor(apiClient) {
|
|
2784
|
-
this.apiClient = apiClient;
|
|
2785
|
-
this.analyticsSDK = createAnalyticsSDK(apiClient);
|
|
2786
|
-
}
|
|
2787
|
-
/**
|
|
2788
|
-
* Get transaction analytics
|
|
2789
|
-
*
|
|
2790
|
-
* @param request - Analytics request parameters
|
|
2791
|
-
* @returns Promise resolving to transaction analytics data
|
|
2792
|
-
*/
|
|
2793
|
-
async getTransactionAnalytics(request) {
|
|
2794
|
-
return this.analyticsSDK.getTransactionAnalytics(request);
|
|
2795
|
-
}
|
|
2796
|
-
/**
|
|
2797
|
-
* Get the full analytics SDK for advanced operations
|
|
2798
|
-
*
|
|
2799
|
-
* @returns AnalyticsSDK instance
|
|
2800
|
-
*/
|
|
2801
|
-
getAnalyticsSDK() {
|
|
2802
|
-
return this.analyticsSDK;
|
|
2803
|
-
}
|
|
2804
|
-
}
|
|
2805
|
-
|
|
2806
|
-
/**
|
|
2807
|
-
* Donation Manager - Clean, high-level interface for donation operations
|
|
2808
|
-
*
|
|
2809
|
-
* Provides a simplified API for common donation tasks while maintaining
|
|
2810
|
-
* access to the full donation SDK for advanced use cases.
|
|
2811
|
-
*/
|
|
2812
|
-
class DonationManager {
|
|
2813
|
-
constructor(apiClient) {
|
|
2814
|
-
this.apiClient = apiClient;
|
|
2815
|
-
this.donationSDK = createDonationSDK(apiClient);
|
|
2816
|
-
}
|
|
2817
|
-
/**
|
|
2818
|
-
* Get available donation types
|
|
2819
|
-
*
|
|
2820
|
-
* @returns Promise resolving to array of donation types
|
|
2821
|
-
*/
|
|
2822
|
-
async getDonationTypes() {
|
|
2823
|
-
return this.donationSDK.getAllDonationTypes();
|
|
2824
|
-
}
|
|
2825
|
-
/**
|
|
2826
|
-
* Get the full donation SDK for advanced operations
|
|
2827
|
-
*
|
|
2828
|
-
* @returns DonationSDK instance
|
|
2829
|
-
*/
|
|
2830
|
-
getDonationSDK() {
|
|
2831
|
-
return this.donationSDK;
|
|
2832
|
-
}
|
|
2833
|
-
}
|
|
2834
|
-
|
|
2835
|
-
/**
|
|
2836
|
-
* Web3 Manager - Clean, high-level interface for Web3 operations
|
|
2837
|
-
*
|
|
2838
|
-
* Provides a simplified API for common Web3 blockchain tasks while maintaining
|
|
2839
|
-
* access to the full Web3 SDK for advanced use cases.
|
|
2840
|
-
*/
|
|
2841
|
-
class Web3Manager {
|
|
2842
|
-
constructor(apiClient) {
|
|
2843
|
-
this.apiClient = apiClient;
|
|
2844
|
-
this.web3SDK = createWeb3SDK(apiClient);
|
|
2845
|
-
this.web3ChainSDK = createWeb3ChainSDK(apiClient);
|
|
2846
|
-
}
|
|
2847
|
-
/**
|
|
2848
|
-
* Get token balance for a specific token
|
|
2849
|
-
*
|
|
2850
|
-
* @param request - Token balance request parameters
|
|
2851
|
-
* @returns Promise resolving to token balance
|
|
2852
|
-
*/
|
|
2853
|
-
async getTokenBalance(request) {
|
|
2854
|
-
return this.web3SDK.getTokenBalance(request);
|
|
2855
|
-
}
|
|
2856
|
-
/**
|
|
2857
|
-
* Get token metadata
|
|
2858
|
-
*
|
|
2859
|
-
* @param request - Token metadata request parameters
|
|
2860
|
-
* @returns Promise resolving to token metadata or null if not found
|
|
2861
|
-
*/
|
|
2862
|
-
async getTokenMetadata(request) {
|
|
2863
|
-
return this.web3SDK.getTokenMetadata(request);
|
|
2864
|
-
}
|
|
2865
|
-
/**
|
|
2866
|
-
* Get token collection
|
|
2867
|
-
*
|
|
2868
|
-
* @param request - Token collection request parameters
|
|
2869
|
-
* @returns Promise resolving to token collection
|
|
2870
|
-
*/
|
|
2871
|
-
async getTokenCollection(request) {
|
|
2872
|
-
return this.web3SDK.getTokenCollection(request);
|
|
2873
|
-
}
|
|
2874
|
-
/**
|
|
2875
|
-
* Resolve IPFS URL to accessible URL
|
|
2876
|
-
*
|
|
2877
|
-
* @param url - IPFS URL to resolve
|
|
2878
|
-
* @param chainId - Chain ID for context
|
|
2879
|
-
* @returns Promise resolving to accessible URL
|
|
2880
|
-
*/
|
|
2881
|
-
async resolveIPFSUrl(url, chainId) {
|
|
2882
|
-
return this.web3SDK.resolveIPFSUrl(url, chainId);
|
|
2883
|
-
}
|
|
2884
|
-
/**
|
|
2885
|
-
* Fetch and process token metadata
|
|
2886
|
-
*
|
|
2887
|
-
* @param tokenUri - Token URI to fetch metadata from
|
|
2888
|
-
* @param chainId - Chain ID for context
|
|
2889
|
-
* @returns Promise resolving to processed metadata or null if not found
|
|
2890
|
-
*/
|
|
2891
|
-
async fetchAndProcessMetadata(tokenUri, chainId) {
|
|
2892
|
-
return this.web3SDK.fetchAndProcessMetadata(tokenUri, chainId);
|
|
2893
|
-
}
|
|
2894
|
-
/**
|
|
2895
|
-
* Get blockchain chain data by chain ID
|
|
2896
|
-
*
|
|
2897
|
-
* @param chainId - Chain ID to get data for
|
|
2898
|
-
* @returns Promise resolving to chain data or null if not found
|
|
2899
|
-
*/
|
|
2900
|
-
async getChainDataById(chainId) {
|
|
2901
|
-
return this.web3ChainSDK.getChainDataById(chainId);
|
|
2902
|
-
}
|
|
2903
|
-
/**
|
|
2904
|
-
* Get explorer URL for a given address or transaction
|
|
2905
|
-
*
|
|
2906
|
-
* @param chainId - Chain ID to get explorer URL for
|
|
2907
|
-
* @param address - Address or transaction hash
|
|
2908
|
-
* @param type - Type of explorer URL ('address' or 'tx')
|
|
2909
|
-
* @returns Promise resolving to explorer URL
|
|
2910
|
-
*/
|
|
2911
|
-
async getExplorerUrl(chainId, address, type) {
|
|
2912
|
-
return getExplorerUrlByChainId((id) => this.getChainDataById(id), chainId, address, type);
|
|
2913
|
-
}
|
|
2914
|
-
/**
|
|
2915
|
-
* Get the full Web3 SDK for advanced operations
|
|
2916
|
-
*
|
|
2917
|
-
* @returns Web3SDK instance
|
|
2918
|
-
*/
|
|
2919
|
-
getWeb3SDK() {
|
|
2920
|
-
return this.web3SDK;
|
|
2921
|
-
}
|
|
2922
|
-
}
|
|
2923
|
-
|
|
2924
|
-
/**
|
|
2925
|
-
* PERS SDK - Platform-agnostic TypeScript SDK with High-Level Managers
|
|
2926
|
-
*
|
|
2927
|
-
* ## Overview
|
|
2928
|
-
*
|
|
2929
|
-
* The PERS SDK provides a comprehensive interface for integrating with the PERS
|
|
2930
|
-
* (Phygital Experience Rewards System) platform. It features a clean manager-based
|
|
2931
|
-
* architecture that abstracts complex domain operations into intuitive high-level APIs.
|
|
2932
|
-
*
|
|
2933
|
-
* ## Architecture
|
|
2934
|
-
*
|
|
2935
|
-
* ```
|
|
2936
|
-
* PersSDK
|
|
2937
|
-
* ├── Domain Managers (Recommended) // High-level, intuitive APIs
|
|
2938
|
-
* │ ├── auth: AuthManager // Authentication & user sessions
|
|
2939
|
-
* │ ├── users: UserManager // User profile management
|
|
2940
|
-
* │ ├── tokens: TokenManager // Token balances & transfers
|
|
2941
|
-
* │ ├── businesses: BusinessManager // Business operations
|
|
2942
|
-
* │ ├── campaigns: CampaignManager // Marketing campaigns
|
|
2943
|
-
* │ ├── redemptions: RedemptionManager // Reward redemptions
|
|
2944
|
-
* │ ├── transactions: TransactionManager // Transaction history
|
|
2945
|
-
* │ ├── purchases: PurchaseManager // Purchase processing
|
|
2946
|
-
* │ └── analytics: AnalyticsManager // Reporting & analytics
|
|
2947
|
-
* ├── Domain SDKs (Advanced) // Full-featured domain access
|
|
2948
|
-
* │ ├── createBusinessSDK()
|
|
2949
|
-
* │ ├── createCampaignSDK()
|
|
2950
|
-
* │ └── TokenSDK, etc.
|
|
2951
|
-
* └── Core API Client (Expert) // Direct REST API access
|
|
2952
|
-
* └── api(): PersApiClient
|
|
2953
|
-
* ```
|
|
2954
|
-
*
|
|
2955
|
-
* ## Usage Patterns
|
|
2956
|
-
*
|
|
2957
|
-
* ### 1. High-Level Manager Pattern (Recommended)
|
|
2958
|
-
*
|
|
2959
|
-
* ```typescript
|
|
2960
|
-
* import { PersSDK } from '@explorins/pers-sdk';
|
|
2961
|
-
* import { BrowserFetchClientAdapter } from '@explorins/pers-sdk/platform-adapters';
|
|
2962
|
-
*
|
|
2963
|
-
* const sdk = new PersSDK(new BrowserFetchClientAdapter(), {
|
|
2964
|
-
* environment: 'production',
|
|
2965
|
-
* apiProjectKey: 'your-project-key'
|
|
2966
|
-
* });
|
|
2967
|
-
*
|
|
2968
|
-
* // Clean, intuitive manager interface
|
|
2969
|
-
* const user = await sdk.auth.getCurrentUser();
|
|
2970
|
-
* const campaigns = await sdk.campaigns.getActiveCampaigns();
|
|
2971
|
-
* const balances = await sdk.tokens.getTokens();
|
|
2972
|
-
* ```
|
|
2973
|
-
*
|
|
2974
|
-
* ### 2. Advanced Domain SDK Access
|
|
2975
|
-
*
|
|
2976
|
-
* ```typescript
|
|
2977
|
-
* // Access full SDK capabilities when needed
|
|
2978
|
-
* const campaignSDK = sdk.campaigns.getCampaignSDK();
|
|
2979
|
-
* const advancedCampaignOps = await campaignSDK.api.createComplexCampaign(data);
|
|
2980
|
-
* ```
|
|
2981
|
-
*
|
|
2982
|
-
* ### 3. Direct API Client Access
|
|
2983
|
-
*
|
|
2984
|
-
* ```typescript
|
|
2985
|
-
* // For custom endpoints or advanced operations
|
|
2986
|
-
* const apiClient = sdk.api();
|
|
2987
|
-
* const customData = await apiClient.get('/custom-endpoint');
|
|
2988
|
-
* ```
|
|
2989
|
-
*
|
|
2990
|
-
* ## Platform Integration
|
|
2991
|
-
*
|
|
2992
|
-
* The SDK provides pre-built adapters for common platforms:
|
|
2993
|
-
*
|
|
2994
|
-
* - **Angular**: `AngularHttpClientAdapter`
|
|
2995
|
-
* - **Browser/React/Vue**: `BrowserFetchClientAdapter`
|
|
2996
|
-
* - **Node.js**: `NodeHttpClientAdapter`
|
|
2997
|
-
* - **Custom**: Implement `HttpClient` interface
|
|
2998
|
-
*
|
|
2999
|
-
* ## Features
|
|
3000
|
-
*
|
|
3001
|
-
* - ✅ **Type-safe**: Full TypeScript support with comprehensive type definitions
|
|
3002
|
-
* - ✅ **Platform-agnostic**: Works in browsers, Node.js, React Native, and more
|
|
3003
|
-
* - ✅ **Authentication**: Automatic token management and refresh
|
|
3004
|
-
* - ✅ **Error handling**: Comprehensive error handling with typed exceptions
|
|
3005
|
-
* - ✅ **Modular**: Import only the domains you need
|
|
3006
|
-
* - ✅ **Manager pattern**: Clean, high-level APIs for common operations
|
|
3007
|
-
* - ✅ **Backward compatible**: Maintains compatibility with existing integrations
|
|
3008
|
-
* - ✅ **Tree-shakable**: Optimized for minimal bundle size
|
|
3009
|
-
*
|
|
3010
|
-
* @example Basic Setup
|
|
3011
|
-
* ```typescript
|
|
3012
|
-
* import { PersSDK } from '@explorins/pers-sdk';
|
|
3013
|
-
* import { BrowserFetchClientAdapter } from '@explorins/pers-sdk/platform-adapters';
|
|
3014
|
-
*
|
|
3015
|
-
* const sdk = new PersSDK(new BrowserFetchClientAdapter(), {
|
|
3016
|
-
* environment: 'production',
|
|
3017
|
-
* apiProjectKey: 'your-project-key'
|
|
3018
|
-
* });
|
|
3019
|
-
* ```
|
|
3020
|
-
*
|
|
3021
|
-
* @example Authentication Flow
|
|
3022
|
-
* ```typescript
|
|
3023
|
-
* // Login with external JWT (Firebase, Auth0, etc.)
|
|
3024
|
-
* await sdk.auth.loginWithToken(firebaseJWT, 'user');
|
|
3025
|
-
*
|
|
3026
|
-
* // Check authentication status
|
|
3027
|
-
* if (await sdk.auth.isAuthenticated()) {
|
|
3028
|
-
* const user = await sdk.auth.getCurrentUser();
|
|
3029
|
-
* console.log('Welcome,', user.name);
|
|
3030
|
-
* }
|
|
3031
|
-
* ```
|
|
3032
|
-
*
|
|
3033
|
-
* @example Business Operations
|
|
3034
|
-
* ```typescript
|
|
3035
|
-
* // Get active businesses
|
|
3036
|
-
* const businesses = await sdk.businesses.getActiveBusinesses();
|
|
3037
|
-
*
|
|
3038
|
-
* // Get business details
|
|
3039
|
-
* const business = await sdk.businesses.getBusinessById(businessId);
|
|
3040
|
-
*
|
|
3041
|
-
* // Admin: Create new business
|
|
3042
|
-
* const newBusiness = await sdk.businesses.createBusiness({
|
|
3043
|
-
* name: 'New Business',
|
|
3044
|
-
* location: 'City Center',
|
|
3045
|
-
* type: 'restaurant'
|
|
3046
|
-
* });
|
|
3047
|
-
* ```
|
|
3048
|
-
*
|
|
3049
|
-
* @example Campaign Management
|
|
3050
|
-
* ```typescript
|
|
3051
|
-
* // Get active campaigns
|
|
3052
|
-
* const campaigns = await sdk.campaigns.getActiveCampaigns();
|
|
3053
|
-
*
|
|
3054
|
-
* // Claim a campaign
|
|
3055
|
-
* await sdk.campaigns.claimCampaign({
|
|
3056
|
-
* campaignId: 'campaign-123',
|
|
3057
|
-
* metadata: { source: 'mobile-app' }
|
|
3058
|
-
* });
|
|
3059
|
-
*
|
|
3060
|
-
* // Get user's claims
|
|
3061
|
-
* const claims = await sdk.campaigns.getUserClaims();
|
|
3062
|
-
* ```
|
|
3063
|
-
*
|
|
3064
|
-
* @example Token Operations
|
|
3065
|
-
* ```typescript
|
|
3066
|
-
* // Get user's token balances
|
|
3067
|
-
* const tokens = await sdk.tokens.getTokens();
|
|
3068
|
-
*
|
|
3069
|
-
* // Transfer tokens between users
|
|
3070
|
-
* await sdk.tokens.transferTokens({
|
|
3071
|
-
* fromUserId: 'user-1',
|
|
3072
|
-
* toUserId: 'user-2',
|
|
3073
|
-
* tokenType: 'CREDIT',
|
|
3074
|
-
* amount: 100
|
|
3075
|
-
* });
|
|
3076
|
-
* ```
|
|
3077
|
-
*
|
|
3078
|
-
* @since 1.3.0 - Manager pattern architecture
|
|
3079
|
-
*/
|
|
3080
|
-
/**
|
|
3081
|
-
* PERS SDK class with domain managers
|
|
3082
|
-
*
|
|
3083
|
-
* Main SDK interface providing clean, high-level managers for common operations
|
|
3084
|
-
* while maintaining full access to the underlying API client and domain SDKs.
|
|
3085
|
-
*
|
|
3086
|
-
* @example
|
|
3087
|
-
* ```typescript
|
|
3088
|
-
* import { PersSDK, createAuthProvider } from '@explorins/pers-sdk/core';
|
|
3089
|
-
* import { BrowserHttpClient } from '@explorins/pers-sdk/browser';
|
|
3090
|
-
*
|
|
3091
|
-
* const authProvider = createAuthProvider({
|
|
3092
|
-
* tokenProvider: () => getFirebaseToken()
|
|
3093
|
-
* });
|
|
3094
|
-
*
|
|
3095
|
-
* const sdk = new PersSDK(new BrowserHttpClient(), {
|
|
3096
|
-
* environment: 'production',
|
|
3097
|
-
* apiProjectKey: 'your-project-key',
|
|
3098
|
-
* authProvider
|
|
3099
|
-
* });
|
|
3100
|
-
*
|
|
3101
|
-
* // High-level manager interface
|
|
3102
|
-
* const user = await sdk.auth.getCurrentUser();
|
|
3103
|
-
* const tokens = await sdk.tokens.getTokens();
|
|
3104
|
-
* const businesses = await sdk.business.getActiveBusinesses();
|
|
3105
|
-
*
|
|
3106
|
-
* // Direct API access for advanced operations
|
|
3107
|
-
* const apiClient = sdk.api();
|
|
3108
|
-
* const customData = await apiClient.get('/custom-endpoint');
|
|
3109
|
-
* ```
|
|
3110
|
-
*/
|
|
3111
|
-
class PersSDK {
|
|
3112
|
-
/**
|
|
3113
|
-
* Creates a new PERS SDK instance
|
|
3114
|
-
*
|
|
3115
|
-
* @param httpClient Platform-specific HTTP client implementation
|
|
3116
|
-
* @param config SDK configuration options
|
|
3117
|
-
*/
|
|
3118
|
-
constructor(httpClient, config) {
|
|
3119
|
-
this.apiClient = new PersApiClient(httpClient, config);
|
|
3120
|
-
// Initialize domain managers
|
|
3121
|
-
this._auth = new AuthManager(this.apiClient);
|
|
3122
|
-
this._users = new UserManager(this.apiClient);
|
|
3123
|
-
this._userStatus = new UserStatusManager(this.apiClient);
|
|
3124
|
-
this._tokens = new TokenManager(this.apiClient);
|
|
3125
|
-
this._businesses = new BusinessManager(this.apiClient);
|
|
3126
|
-
this._campaigns = new CampaignManager(this.apiClient);
|
|
3127
|
-
this._redemptions = new RedemptionManager(this.apiClient);
|
|
3128
|
-
this._transactions = new TransactionManager(this.apiClient);
|
|
3129
|
-
this._purchases = new PurchaseManager(this.apiClient);
|
|
3130
|
-
this._files = new FileManager(this.apiClient);
|
|
3131
|
-
this._tenants = new TenantManager(this.apiClient);
|
|
3132
|
-
this._analytics = new AnalyticsManager(this.apiClient);
|
|
3133
|
-
this._donations = new DonationManager(this.apiClient);
|
|
3134
|
-
this._web3 = new Web3Manager(this.apiClient);
|
|
3135
|
-
}
|
|
3136
|
-
/**
|
|
3137
|
-
* Authentication manager - High-level auth operations
|
|
3138
|
-
*
|
|
3139
|
-
* @example
|
|
3140
|
-
* ```typescript
|
|
3141
|
-
* await sdk.auth.loginWithToken(jwtToken);
|
|
3142
|
-
* const user = await sdk.auth.getCurrentUser();
|
|
3143
|
-
* const isAuth = await sdk.auth.isAuthenticated();
|
|
3144
|
-
* ```
|
|
3145
|
-
*/
|
|
3146
|
-
get auth() {
|
|
3147
|
-
return this._auth;
|
|
3148
|
-
}
|
|
3149
|
-
/**
|
|
3150
|
-
* User manager - High-level user operations
|
|
3151
|
-
*
|
|
3152
|
-
* @example
|
|
3153
|
-
* ```typescript
|
|
3154
|
-
* const user = await sdk.user.getCurrentUser();
|
|
3155
|
-
* await sdk.user.updateCurrentUser(userData);
|
|
3156
|
-
* const users = await sdk.user.getAllUsersPublic();
|
|
3157
|
-
* ```
|
|
3158
|
-
*/
|
|
3159
|
-
get users() {
|
|
3160
|
-
return this._users;
|
|
3161
|
-
}
|
|
3162
|
-
/**
|
|
3163
|
-
* User Status manager - High-level user status operations
|
|
3164
|
-
*
|
|
3165
|
-
* @example
|
|
3166
|
-
* ```typescript
|
|
3167
|
-
* const statusTypes = await sdk.userStatus.getUserStatusTypes();
|
|
3168
|
-
* const earnedStatus = await sdk.userStatus.getEarnedUserStatus();
|
|
3169
|
-
* await sdk.userStatus.createUserStatusType(statusData);
|
|
3170
|
-
* ```
|
|
3171
|
-
*/
|
|
3172
|
-
get userStatus() {
|
|
3173
|
-
return this._userStatus;
|
|
3174
|
-
}
|
|
3175
|
-
/**
|
|
3176
|
-
* Token manager - High-level token operations
|
|
3177
|
-
*
|
|
3178
|
-
* @example
|
|
3179
|
-
* ```typescript
|
|
3180
|
-
* const tokens = await sdk.tokens.getTokens();
|
|
3181
|
-
* const creditToken = await sdk.tokens.getActiveCreditToken();
|
|
3182
|
-
* const rewards = await sdk.tokens.getRewardTokens();
|
|
3183
|
-
* ```
|
|
3184
|
-
*/
|
|
3185
|
-
get tokens() {
|
|
3186
|
-
return this._tokens;
|
|
3187
|
-
}
|
|
3188
|
-
/**
|
|
3189
|
-
* Business manager - High-level business operations
|
|
3190
|
-
*
|
|
3191
|
-
* @example
|
|
3192
|
-
* ```typescript
|
|
3193
|
-
* const businesses = await sdk.business.getActiveBusinesses();
|
|
3194
|
-
* const business = await sdk.business.getBusinessById(id);
|
|
3195
|
-
* const types = await sdk.business.getBusinessTypes();
|
|
3196
|
-
* ```
|
|
3197
|
-
*/
|
|
3198
|
-
get businesses() {
|
|
3199
|
-
return this._businesses;
|
|
3200
|
-
}
|
|
3201
|
-
/**
|
|
3202
|
-
* Campaign manager - High-level campaign operations
|
|
3203
|
-
*
|
|
3204
|
-
* @example
|
|
3205
|
-
* ```typescript
|
|
3206
|
-
* const campaigns = await sdk.campaigns.getActiveCampaigns();
|
|
3207
|
-
* await sdk.campaigns.claimCampaign(claimData);
|
|
3208
|
-
* const claims = await sdk.campaigns.getUserClaims();
|
|
3209
|
-
* ```
|
|
3210
|
-
*/
|
|
3211
|
-
get campaigns() {
|
|
3212
|
-
return this._campaigns;
|
|
3213
|
-
}
|
|
3214
|
-
/**
|
|
3215
|
-
* Redemption manager - High-level redemption operations
|
|
3216
|
-
*
|
|
3217
|
-
* @example
|
|
3218
|
-
* ```typescript
|
|
3219
|
-
* const redemptions = await sdk.redemptions.getActiveRedemptions();
|
|
3220
|
-
* await sdk.redemptions.redeemOffer(redemptionId);
|
|
3221
|
-
* const history = await sdk.redemptions.getUserRedemptions();
|
|
3222
|
-
* ```
|
|
3223
|
-
*/
|
|
3224
|
-
get redemptions() {
|
|
3225
|
-
return this._redemptions;
|
|
3226
|
-
}
|
|
3227
|
-
/**
|
|
3228
|
-
* Transaction manager - High-level transaction operations
|
|
3229
|
-
*
|
|
3230
|
-
* @example
|
|
3231
|
-
* ```typescript
|
|
3232
|
-
* const transaction = await sdk.transactions.getTransactionById(id);
|
|
3233
|
-
* await sdk.transactions.createTransaction(txData);
|
|
3234
|
-
* const history = await sdk.transactions.getUserTransactionHistory('all');
|
|
3235
|
-
* ```
|
|
3236
|
-
*/
|
|
3237
|
-
get transactions() {
|
|
3238
|
-
return this._transactions;
|
|
3239
|
-
}
|
|
3240
|
-
/**
|
|
3241
|
-
* Purchase manager - High-level purchase operations
|
|
3242
|
-
*
|
|
3243
|
-
* @example
|
|
3244
|
-
* ```typescript
|
|
3245
|
-
* const intent = await sdk.purchases.createPaymentIntent(100, 'usd', 'email@example.com', 'Purchase');
|
|
3246
|
-
* const tokens = await sdk.purchases.getActivePurchaseTokens();
|
|
3247
|
-
* const purchases = await sdk.purchases.getAllUserPurchases();
|
|
3248
|
-
* ```
|
|
3249
|
-
*/
|
|
3250
|
-
get purchases() {
|
|
3251
|
-
return this._purchases;
|
|
3252
|
-
}
|
|
3253
|
-
/**
|
|
3254
|
-
* File manager - High-level file operations
|
|
3255
|
-
*
|
|
3256
|
-
* @example
|
|
3257
|
-
* ```typescript
|
|
3258
|
-
* const uploadUrl = await sdk.files.getSignedPutUrl('entity-123', 'token', 'jpg');
|
|
3259
|
-
* const accessUrl = await sdk.files.getSignedGetUrl('entity-123', 'token');
|
|
3260
|
-
* const optimizedUrl = await sdk.files.optimizeMedia(originalUrl, 800, 600);
|
|
3261
|
-
* ```
|
|
3262
|
-
*/
|
|
3263
|
-
get files() {
|
|
3264
|
-
return this._files;
|
|
3265
|
-
}
|
|
3266
|
-
/**
|
|
3267
|
-
* Tenant manager - High-level tenant operations
|
|
3268
|
-
*
|
|
3269
|
-
* @example
|
|
3270
|
-
* ```typescript
|
|
3271
|
-
* const tenant = await sdk.tenant.getTenantInfo();
|
|
3272
|
-
* const config = await sdk.tenant.getClientConfig();
|
|
3273
|
-
* const admins = await sdk.tenant.getAdmins();
|
|
3274
|
-
* ```
|
|
3275
|
-
*/
|
|
3276
|
-
get tenants() {
|
|
3277
|
-
return this._tenants;
|
|
3278
|
-
}
|
|
3279
|
-
/**
|
|
3280
|
-
* Analytics manager - High-level analytics operations
|
|
3281
|
-
*
|
|
3282
|
-
* @example
|
|
3283
|
-
* ```typescript
|
|
3284
|
-
* const analytics = await sdk.analytics.getTransactionAnalytics(request);
|
|
3285
|
-
* ```
|
|
3286
|
-
*/
|
|
3287
|
-
get analytics() {
|
|
3288
|
-
return this._analytics;
|
|
3289
|
-
}
|
|
3290
|
-
/**
|
|
3291
|
-
* Donation manager - High-level donation operations
|
|
3292
|
-
*
|
|
3293
|
-
* @example
|
|
3294
|
-
* ```typescript
|
|
3295
|
-
* const types = await sdk.donations.getDonationTypes();
|
|
3296
|
-
* ```
|
|
3297
|
-
*/
|
|
3298
|
-
get donations() {
|
|
3299
|
-
return this._donations;
|
|
3300
|
-
}
|
|
3301
|
-
/**
|
|
3302
|
-
* Web3 manager - High-level blockchain operations
|
|
3303
|
-
*
|
|
3304
|
-
* @example
|
|
3305
|
-
* ```typescript
|
|
3306
|
-
* const balance = await sdk.web3.getTokenBalance(request);
|
|
3307
|
-
* const metadata = await sdk.web3.getTokenMetadata(request);
|
|
3308
|
-
* const collection = await sdk.web3.getTokenCollection(request);
|
|
3309
|
-
* ```
|
|
3310
|
-
*/
|
|
3311
|
-
get web3() {
|
|
3312
|
-
return this._web3;
|
|
3313
|
-
}
|
|
3314
|
-
/**
|
|
3315
|
-
* Gets the API client for direct PERS API requests
|
|
3316
|
-
*
|
|
3317
|
-
* Use this for advanced operations not covered by the managers.
|
|
3318
|
-
* The returned client handles authentication, token refresh, and error handling automatically.
|
|
3319
|
-
*
|
|
3320
|
-
* @returns Configured PersApiClient instance
|
|
3321
|
-
*
|
|
3322
|
-
* @example
|
|
3323
|
-
* ```typescript
|
|
3324
|
-
* const apiClient = sdk.api();
|
|
3325
|
-
* const customData = await apiClient.get<CustomType>('/custom-endpoint');
|
|
3326
|
-
* await apiClient.post('/custom-endpoint', customData);
|
|
3327
|
-
* ```
|
|
3328
|
-
*/
|
|
3329
|
-
api() {
|
|
3330
|
-
return this.apiClient;
|
|
3331
|
-
}
|
|
3332
|
-
/**
|
|
3333
|
-
* Checks if SDK is configured for production environment
|
|
3334
|
-
*
|
|
3335
|
-
* @returns True if environment is 'production', false otherwise
|
|
3336
|
-
*/
|
|
3337
|
-
isProduction() {
|
|
3338
|
-
return this.apiClient.getConfig().environment === 'production';
|
|
3339
|
-
}
|
|
3340
|
-
}
|
|
3341
|
-
/**
|
|
3342
|
-
* Factory function for creating PERS SDK
|
|
3343
|
-
*
|
|
3344
|
-
* @param httpClient Platform-specific HTTP client implementation
|
|
3345
|
-
* @param config SDK configuration options
|
|
3346
|
-
* @returns PERS SDK instance
|
|
3347
|
-
*/
|
|
3348
|
-
function createPersSDK(httpClient, config) {
|
|
3349
|
-
return new PersSDK(httpClient, config);
|
|
3350
|
-
}
|
|
3351
|
-
|
|
3352
|
-
export { AuthManager as A, BusinessManager as B, CampaignManager as C, DEFAULT_PERS_CONFIG as D, FileManager as F, PersSDK as P, RedemptionManager as R, TokenManager as T, UserManager as U, Web3Manager as W, createAuthProvider as a, PersApiClient as b, createPersSDK as c, buildApiRoot as d, UserStatusManager as e, TransactionManager as f, PurchaseManager as g, TenantManager as h, AnalyticsManager as i, DonationManager as j, FileApi as k, FileService as l, mergeWithDefaults as m, createFileSDK as n };
|
|
3353
|
-
//# sourceMappingURL=pers-sdk-Z6MKeFBX.js.map
|