@explorins/pers-sdk 1.0.0-alpha.1 → 1.1.2
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/config/domains.js +22 -0
- package/explorins-pers-sdk-1.0.0-alpha.1.tgz +0 -0
- package/package.json +116 -23
- package/rollup.config.js +50 -54
- package/scripts/copy-declarations.js +147 -0
- package/src/analytics/api/analytics-api.ts +24 -0
- package/src/analytics/index.ts +52 -0
- package/src/analytics/models/index.ts +74 -0
- package/src/analytics/services/analytics-service.ts +28 -0
- package/src/auth-admin/api/auth-admin-api.ts +42 -0
- package/src/auth-admin/index.ts +47 -0
- package/src/auth-admin/services/auth-admin-service.ts +36 -0
- package/src/business/api/business-api.ts +181 -19
- package/src/business/index.ts +4 -3
- package/src/business/models/index.ts +4 -4
- package/src/business/services/business-service.ts +1 -1
- package/src/campaign/api/campaign-api.ts +376 -0
- package/src/campaign/index.ts +67 -0
- package/src/campaign/services/campaign-service.ts +164 -0
- package/src/core/abstractions/http-client.ts +1 -0
- package/src/core/auth/auth-provider.interface.ts +2 -2
- package/src/core/auth/create-auth-provider.ts +6 -6
- package/src/core/index.ts +33 -0
- package/src/core/pers-api-client.ts +211 -19
- package/src/core/pers-config.ts +34 -7
- package/src/core/utils/jwt.function.ts +24 -0
- package/src/donation/api/donation-api.ts +24 -0
- package/src/donation/index.ts +47 -0
- package/src/donation/models/index.ts +11 -0
- package/src/donation/services/donation-service.ts +25 -0
- package/src/index.ts +40 -1
- package/src/payment/api/payment-api.ts +185 -0
- package/src/payment/index.ts +64 -0
- package/src/payment/models/index.ts +29 -0
- package/src/payment/services/payment-service.ts +70 -0
- package/src/redemption/api/redemption-api.ts +241 -0
- package/src/redemption/index.ts +60 -0
- package/src/redemption/models/index.ts +17 -0
- package/src/redemption/services/redemption-service.ts +103 -0
- package/src/shared/interfaces/pers-shared-lib.interfaces.ts +99 -0
- package/src/tenant/api/tenant-api.ts +92 -0
- package/src/tenant/index.ts +61 -0
- package/src/tenant/models/index.ts +20 -0
- package/src/tenant/services/tenant-service.ts +78 -0
- package/src/token/api/token-api.ts +129 -0
- package/src/token/base/base-token-service.ts +167 -0
- package/src/token/index.ts +38 -0
- package/src/token/models/index.ts +30 -0
- package/src/token/services/token-service.ts +125 -0
- package/src/token/token-sdk.ts +231 -0
- package/src/transaction/api/transaction-api.ts +296 -0
- package/src/transaction/index.ts +65 -0
- package/src/transaction/models/index.ts +60 -0
- package/src/transaction/services/transaction-service.ts +104 -0
- package/src/user/api/user-api.ts +98 -0
- package/src/user/index.ts +62 -0
- package/src/user/models/index.ts +10 -0
- package/src/user/services/user-service.ts +75 -0
- package/src/user-status/api/user-status-api.ts +78 -0
- package/src/user-status/index.ts +55 -0
- package/src/user-status/models/index.ts +11 -0
- package/src/user-status/services/user-status-service.ts +51 -0
- package/src/web3/api/web3-api.ts +68 -0
- package/src/web3/index.ts +38 -0
- package/src/web3/models/index.ts +150 -0
- package/src/web3/services/web3-service.ts +338 -0
- package/src/web3-chain/api/web3-chain-api.ts +42 -0
- package/src/web3-chain/index.ts +27 -0
- package/src/web3-chain/models/index.ts +45 -0
- package/src/web3-chain/services/getWeb3FCD.service.ts +47 -0
- package/src/web3-chain/services/provider.service.ts +123 -0
- package/src/web3-chain/services/public-http-provider.service.ts +26 -0
- package/src/web3-chain/services/web3-chain-service.ts +131 -0
- package/src/business/business/tsconfig.json +0 -18
- package/src/core/abstractions/core-interfaces.ts +0 -56
- package/src/core/core.ts +0 -30
- package/src/core.ts +0 -30
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @explorins/pers-sdk/core - Core SDK Entry Point
|
|
3
|
+
*
|
|
4
|
+
* Platform-agnostic PERS API client and core functionality
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Core PERS API client
|
|
8
|
+
export * from './pers-api-client';
|
|
9
|
+
|
|
10
|
+
// Configuration interfaces and types
|
|
11
|
+
export * from './pers-config';
|
|
12
|
+
export type { PersEnvironment, PersApiVersion } from './pers-config';
|
|
13
|
+
|
|
14
|
+
// Authentication interfaces
|
|
15
|
+
export {
|
|
16
|
+
PersAuthProvider,
|
|
17
|
+
SimpleAuthConfig,
|
|
18
|
+
createAuthProvider,
|
|
19
|
+
/* createBrowserTokenProvider,
|
|
20
|
+
createNodeTokenProvider */
|
|
21
|
+
} from './auth/auth-provider.interface';
|
|
22
|
+
|
|
23
|
+
// Add compatibility alias for Angular package
|
|
24
|
+
// export { PersAuthProvider as AuthProvider } from './auth/auth-provider.interface';
|
|
25
|
+
|
|
26
|
+
export type { PersRequestOptions as AuthRequestOptions } from './auth/auth-provider.interface';
|
|
27
|
+
|
|
28
|
+
// Platform abstractions
|
|
29
|
+
export * from './abstractions/http-client';
|
|
30
|
+
|
|
31
|
+
// Main SDK class
|
|
32
|
+
export { PersSDK, createPersSDK } from '../pers-sdk';
|
|
33
|
+
|
|
@@ -1,19 +1,24 @@
|
|
|
1
|
+
// packages/pers-sdk/src/core/pers-api-client.ts
|
|
1
2
|
/**
|
|
2
3
|
* PERS API Client - Core platform-agnostic client for PERS backend
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
import { HttpClient, RequestOptions } from './abstractions/http-client';
|
|
6
|
-
import { PersConfig, buildApiRoot } from './pers-config';
|
|
7
|
+
import { PersConfig, buildApiRoot, mergeWithDefaults } from './pers-config';
|
|
7
8
|
|
|
8
9
|
export class PersApiClient {
|
|
9
10
|
private readonly apiRoot: string;
|
|
11
|
+
private readonly mergedConfig: ReturnType<typeof mergeWithDefaults>;
|
|
10
12
|
|
|
11
13
|
constructor(
|
|
12
14
|
private httpClient: HttpClient,
|
|
13
15
|
private config: PersConfig
|
|
14
16
|
) {
|
|
15
|
-
//
|
|
16
|
-
this.
|
|
17
|
+
// Merge user config with defaults (production + v2)
|
|
18
|
+
this.mergedConfig = mergeWithDefaults(config);
|
|
19
|
+
|
|
20
|
+
// Build API root from merged environment and version
|
|
21
|
+
this.apiRoot = buildApiRoot(this.mergedConfig.environment, this.mergedConfig.apiVersion);
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
/**
|
|
@@ -25,22 +30,22 @@ export class PersApiClient {
|
|
|
25
30
|
};
|
|
26
31
|
|
|
27
32
|
// Add authentication token
|
|
28
|
-
if (this.
|
|
29
|
-
const token = await this.
|
|
33
|
+
if (this.mergedConfig.authProvider) {
|
|
34
|
+
const token = await this.mergedConfig.authProvider.getToken();
|
|
30
35
|
if (token) {
|
|
31
36
|
headers['Authorization'] = `Bearer ${token}`;
|
|
32
37
|
}
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
// Add project key
|
|
36
|
-
if (this.
|
|
37
|
-
const projectKey = await this.
|
|
41
|
+
if (this.mergedConfig.authProvider) {
|
|
42
|
+
const projectKey = await this.mergedConfig.authProvider.getProjectKey();
|
|
38
43
|
if (projectKey) {
|
|
39
44
|
headers['x-project-key'] = projectKey;
|
|
40
45
|
}
|
|
41
|
-
} else {
|
|
46
|
+
} else if(this.mergedConfig.apiProjectKey) {
|
|
42
47
|
// Fallback to config project key if no auth provider
|
|
43
|
-
headers['x-project-key'] = this.
|
|
48
|
+
headers['x-project-key'] = this.mergedConfig.apiProjectKey;
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
return headers;
|
|
@@ -50,6 +55,186 @@ export class PersApiClient {
|
|
|
50
55
|
* Make a request with proper headers, auth, and error handling
|
|
51
56
|
*/
|
|
52
57
|
private async request<T>(
|
|
58
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE',
|
|
59
|
+
endpoint: string,
|
|
60
|
+
body?: unknown,
|
|
61
|
+
options?: { retryCount?: number; responseType?: 'json' | 'blob' | 'text' | 'arraybuffer' }
|
|
62
|
+
): Promise<T> {
|
|
63
|
+
const { retryCount = 0, responseType = 'json' } = options || {};
|
|
64
|
+
const url = `${this.apiRoot}${endpoint}`;
|
|
65
|
+
|
|
66
|
+
// ✅ DEBUGGING: Add extensive logging for CSV endpoint
|
|
67
|
+
const isCSVEndpoint = endpoint.includes('/export/csv');
|
|
68
|
+
|
|
69
|
+
const requestOptions: RequestOptions = {
|
|
70
|
+
headers: await this.getHeaders(),
|
|
71
|
+
timeout: this.mergedConfig.timeout,
|
|
72
|
+
responseType
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
let result: T;
|
|
77
|
+
|
|
78
|
+
switch (method) {
|
|
79
|
+
case 'GET':
|
|
80
|
+
result = await this.httpClient.get<T>(url, requestOptions);
|
|
81
|
+
break;
|
|
82
|
+
case 'POST':
|
|
83
|
+
result = await this.httpClient.post<T>(url, body, requestOptions);
|
|
84
|
+
break;
|
|
85
|
+
case 'PUT':
|
|
86
|
+
result = await this.httpClient.put<T>(url, body, requestOptions);
|
|
87
|
+
break;
|
|
88
|
+
case 'DELETE':
|
|
89
|
+
result = await this.httpClient.delete<T>(url, requestOptions);
|
|
90
|
+
break;
|
|
91
|
+
default:
|
|
92
|
+
throw new Error(`Unsupported HTTP method: ${method}`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return result;
|
|
96
|
+
} catch (error: unknown) {
|
|
97
|
+
if (isCSVEndpoint) {
|
|
98
|
+
console.error('❌ [PERS API CLIENT] CSV Request failed:', error);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Handle 401 errors with automatic token refresh
|
|
102
|
+
const apiError = error as { status?: number; message?: string };
|
|
103
|
+
|
|
104
|
+
if (apiError.status === 401 && retryCount === 0 && this.mergedConfig.authProvider?.onTokenExpired) {
|
|
105
|
+
try {
|
|
106
|
+
await this.mergedConfig.authProvider.onTokenExpired();
|
|
107
|
+
// Retry once with refreshed token
|
|
108
|
+
return this.request<T>(method, endpoint, body, { ...options, retryCount: 1 });
|
|
109
|
+
} catch (refreshError) {
|
|
110
|
+
throw new PersApiError(
|
|
111
|
+
`Authentication refresh failed: ${refreshError}`,
|
|
112
|
+
endpoint,
|
|
113
|
+
method,
|
|
114
|
+
401
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
throw new PersApiError(
|
|
120
|
+
`PERS API request failed: ${apiError.message || error}`,
|
|
121
|
+
endpoint,
|
|
122
|
+
method,
|
|
123
|
+
apiError.status
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Generic GET request
|
|
130
|
+
*/
|
|
131
|
+
async get<T>(endpoint: string, responseType?: 'json' | 'blob' | 'text' | 'arraybuffer'): Promise<T> {
|
|
132
|
+
return this.request<T>('GET', endpoint, undefined, { responseType });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Generic POST request
|
|
137
|
+
*/
|
|
138
|
+
async post<T>(endpoint: string, body?: unknown): Promise<T> {
|
|
139
|
+
return this.request<T>('POST', endpoint, body);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Generic PUT request
|
|
144
|
+
*/
|
|
145
|
+
async put<T>(endpoint: string, body?: unknown): Promise<T> {
|
|
146
|
+
return this.request<T>('PUT', endpoint, body);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Generic DELETE request
|
|
151
|
+
*/
|
|
152
|
+
async delete<T>(endpoint: string): Promise<T> {
|
|
153
|
+
return this.request<T>('DELETE', endpoint);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Get current configuration (returns merged config)
|
|
158
|
+
*/
|
|
159
|
+
getConfig(): ReturnType<typeof mergeWithDefaults> {
|
|
160
|
+
return this.mergedConfig;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get original user configuration
|
|
165
|
+
*/
|
|
166
|
+
getOriginalConfig(): PersConfig {
|
|
167
|
+
return this.config;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export class PersApiError extends Error {
|
|
172
|
+
constructor(
|
|
173
|
+
message: string,
|
|
174
|
+
public endpoint: string,
|
|
175
|
+
public method: string,
|
|
176
|
+
public statusCode?: number
|
|
177
|
+
) {
|
|
178
|
+
super(message);
|
|
179
|
+
this.name = 'PersApiError';
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* PERS API Client - Core platform-agnostic client for PERS backend
|
|
184
|
+
*/
|
|
185
|
+
|
|
186
|
+
/*import { HttpClient, RequestOptions } from './abstractions/http-client';
|
|
187
|
+
import { PersConfig, buildApiRoot, mergeWithDefaults } from './pers-config';
|
|
188
|
+
|
|
189
|
+
export class PersApiClient {
|
|
190
|
+
private readonly apiRoot: string;
|
|
191
|
+
private readonly mergedConfig: ReturnType<typeof mergeWithDefaults>;
|
|
192
|
+
|
|
193
|
+
constructor(
|
|
194
|
+
private httpClient: HttpClient,
|
|
195
|
+
private config: PersConfig
|
|
196
|
+
) {
|
|
197
|
+
// Merge user config with defaults (production + v2)
|
|
198
|
+
this.mergedConfig = mergeWithDefaults(config);
|
|
199
|
+
|
|
200
|
+
// Build API root from merged environment and version
|
|
201
|
+
this.apiRoot = buildApiRoot(this.mergedConfig.environment, this.mergedConfig.apiVersion);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Get request headers including auth token and project key
|
|
206
|
+
*/
|
|
207
|
+
/*private async getHeaders(): Promise<Record<string, string>> {
|
|
208
|
+
const headers: Record<string, string> = {
|
|
209
|
+
'Content-Type': 'application/json',
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// Add authentication token
|
|
213
|
+
if (this.mergedConfig.authProvider) {
|
|
214
|
+
const token = await this.mergedConfig.authProvider.getToken();
|
|
215
|
+
if (token) {
|
|
216
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Add project key
|
|
221
|
+
if (this.mergedConfig.authProvider) {
|
|
222
|
+
const projectKey = await this.mergedConfig.authProvider.getProjectKey();
|
|
223
|
+
if (projectKey) {
|
|
224
|
+
headers['x-project-key'] = projectKey;
|
|
225
|
+
}
|
|
226
|
+
} else if(this.mergedConfig.apiProjectKey) {
|
|
227
|
+
// Fallback to config project key if no auth provider
|
|
228
|
+
headers['x-project-key'] = this.mergedConfig.apiProjectKey;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return headers;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Make a request with proper headers, auth, and error handling
|
|
236
|
+
*/
|
|
237
|
+
/*private async request<T>(
|
|
53
238
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE',
|
|
54
239
|
endpoint: string,
|
|
55
240
|
body?: any,
|
|
@@ -60,7 +245,7 @@ export class PersApiClient {
|
|
|
60
245
|
|
|
61
246
|
const requestOptions: RequestOptions = {
|
|
62
247
|
headers: await this.getHeaders(),
|
|
63
|
-
timeout: this.
|
|
248
|
+
timeout: this.mergedConfig.timeout,
|
|
64
249
|
};
|
|
65
250
|
|
|
66
251
|
try {
|
|
@@ -78,9 +263,9 @@ export class PersApiClient {
|
|
|
78
263
|
}
|
|
79
264
|
} catch (error: any) {
|
|
80
265
|
// Handle 401 errors with automatic token refresh
|
|
81
|
-
if (error.status === 401 && retryCount === 0 && this.
|
|
266
|
+
if (error.status === 401 && retryCount === 0 && this.mergedConfig.authProvider?.onTokenExpired) {
|
|
82
267
|
try {
|
|
83
|
-
await this.
|
|
268
|
+
await this.mergedConfig.authProvider.onTokenExpired();
|
|
84
269
|
// Retry once with refreshed token
|
|
85
270
|
return this.request<T>(method, endpoint, body, { ...options, retryCount: 1 });
|
|
86
271
|
} catch (refreshError) {
|
|
@@ -105,35 +290,42 @@ export class PersApiClient {
|
|
|
105
290
|
/**
|
|
106
291
|
* Generic GET request
|
|
107
292
|
*/
|
|
108
|
-
async get<T>(endpoint: string): Promise<T> {
|
|
293
|
+
/*async get<T>(endpoint: string): Promise<T> {
|
|
109
294
|
return this.request<T>('GET', endpoint);
|
|
110
295
|
}
|
|
111
296
|
|
|
112
297
|
/**
|
|
113
298
|
* Generic POST request
|
|
114
299
|
*/
|
|
115
|
-
async post<T>(endpoint: string, body?: any): Promise<T> {
|
|
300
|
+
/*async post<T>(endpoint: string, body?: any): Promise<T> {
|
|
116
301
|
return this.request<T>('POST', endpoint, body);
|
|
117
302
|
}
|
|
118
303
|
|
|
119
304
|
/**
|
|
120
305
|
* Generic PUT request
|
|
121
306
|
*/
|
|
122
|
-
async put<T>(endpoint: string, body?: any): Promise<T> {
|
|
307
|
+
/*async put<T>(endpoint: string, body?: any): Promise<T> {
|
|
123
308
|
return this.request<T>('PUT', endpoint, body);
|
|
124
309
|
}
|
|
125
310
|
|
|
126
311
|
/**
|
|
127
312
|
* Generic DELETE request
|
|
128
313
|
*/
|
|
129
|
-
async delete<T>(endpoint: string): Promise<T> {
|
|
314
|
+
/*async delete<T>(endpoint: string): Promise<T> {
|
|
130
315
|
return this.request<T>('DELETE', endpoint);
|
|
131
316
|
}
|
|
132
317
|
|
|
133
318
|
/**
|
|
134
|
-
* Get current configuration
|
|
319
|
+
* Get current configuration (returns merged config)
|
|
320
|
+
*/
|
|
321
|
+
/*getConfig(): ReturnType<typeof mergeWithDefaults> {
|
|
322
|
+
return this.mergedConfig;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Get original user configuration
|
|
135
327
|
*/
|
|
136
|
-
|
|
328
|
+
/*getOriginalConfig(): PersConfig {
|
|
137
329
|
return this.config;
|
|
138
330
|
}
|
|
139
331
|
}
|
|
@@ -148,4 +340,4 @@ export class PersApiError extends Error {
|
|
|
148
340
|
super(message);
|
|
149
341
|
this.name = 'PersApiError';
|
|
150
342
|
}
|
|
151
|
-
}
|
|
343
|
+
}*/
|
package/src/core/pers-config.ts
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
* PERS SDK Configuration interfaces
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { PersAuthProvider } from './auth/auth-provider.interface';
|
|
6
6
|
|
|
7
7
|
export type PersEnvironment = 'development' | 'staging' | 'production';
|
|
8
8
|
export type PersApiVersion = 'v1' | 'v1.8' | 'v1.9' | 'v2';
|
|
9
9
|
|
|
10
10
|
export interface PersConfig {
|
|
11
|
-
environment
|
|
12
|
-
apiProjectKey
|
|
11
|
+
environment?: PersEnvironment;
|
|
12
|
+
apiProjectKey?: string;
|
|
13
13
|
apiVersion?: PersApiVersion;
|
|
14
14
|
timeout?: number;
|
|
15
15
|
retries?: number;
|
|
16
|
-
authProvider?:
|
|
16
|
+
authProvider?: PersAuthProvider;
|
|
17
17
|
// Internal - constructed automatically
|
|
18
18
|
readonly apiRoot?: string;
|
|
19
19
|
}
|
|
@@ -24,15 +24,42 @@ export interface PersAuthConfig {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Default configuration values
|
|
28
28
|
*/
|
|
29
|
+
export const DEFAULT_PERS_CONFIG = {
|
|
30
|
+
environment: 'production' as PersEnvironment,
|
|
31
|
+
apiVersion: 'v2' as PersApiVersion,
|
|
32
|
+
timeout: 30000,
|
|
33
|
+
retries: 3
|
|
34
|
+
} as const;
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Internal function to construct API root from environment
|
|
38
|
+
* Now defaults to production and v2
|
|
39
|
+
*/
|
|
40
|
+
export function buildApiRoot(
|
|
41
|
+
environment: PersEnvironment = 'production',
|
|
42
|
+
version: PersApiVersion = 'v2'
|
|
43
|
+
): string {
|
|
31
44
|
const baseUrls = {
|
|
32
45
|
development: 'https://explorins-loyalty.ngrok.io',
|
|
33
46
|
staging: `https://dev.api.pers.ninja/${version}`,
|
|
34
|
-
production: `https://
|
|
47
|
+
production: `https://api.pers.ninja/${version}`
|
|
35
48
|
};
|
|
36
49
|
|
|
37
50
|
return `${baseUrls[environment]}`;
|
|
38
51
|
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Merge user config with defaults
|
|
55
|
+
*/
|
|
56
|
+
export function mergeWithDefaults(config: PersConfig): PersConfig & Required<Pick<PersConfig, 'environment' | 'apiVersion' | 'timeout' | 'retries'>> {
|
|
57
|
+
return {
|
|
58
|
+
...DEFAULT_PERS_CONFIG,
|
|
59
|
+
...config,
|
|
60
|
+
environment: config.environment ?? DEFAULT_PERS_CONFIG.environment,
|
|
61
|
+
apiVersion: config.apiVersion ?? DEFAULT_PERS_CONFIG.apiVersion,
|
|
62
|
+
timeout: config.timeout ?? DEFAULT_PERS_CONFIG.timeout,
|
|
63
|
+
retries: config.retries ?? DEFAULT_PERS_CONFIG.retries
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jwtDecode } from "jwt-decode";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export const isTokenExpired = (token: string, margin: number = 60): boolean => {
|
|
5
|
+
// ✅ SANITIZE: Remove any words (Bearer etc) if exists and get the token
|
|
6
|
+
const cleanToken = token.split(' ')[1] || token;
|
|
7
|
+
|
|
8
|
+
// ✅ VALIDATION: Check if token is jwt
|
|
9
|
+
if (!cleanToken || cleanToken.split('.').length !== 3) {
|
|
10
|
+
return true; // Consider invalid tokens as expired
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
// ✅ TYPE-SAFE: Decode with proper typing
|
|
15
|
+
const decoded: any = jwtDecode(cleanToken);
|
|
16
|
+
const currentTime = Math.floor(Date.now() / 1000);
|
|
17
|
+
|
|
18
|
+
// ✅ CONFIGURABLE: Use provided margin (default 60 seconds)
|
|
19
|
+
return decoded.exp < (currentTime + margin);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error('[SDK JWT Utils] Error decoding JWT token:', error);
|
|
22
|
+
return true; // Consider unparseable tokens as expired
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PersApiClient } from '../../core/pers-api-client';
|
|
2
|
+
import { DonationTypeDTO } from '../../shared/interfaces/pers-shared-lib.interfaces';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Platform-Agnostic Donation API Client
|
|
6
|
+
*
|
|
7
|
+
* Handles donation operations using the PERS backend.
|
|
8
|
+
* Matches framework DonationApiService methods exactly.
|
|
9
|
+
*/
|
|
10
|
+
export class DonationApi {
|
|
11
|
+
constructor(private apiClient: PersApiClient) {}
|
|
12
|
+
|
|
13
|
+
// ==========================================
|
|
14
|
+
// PUBLIC OPERATIONS
|
|
15
|
+
// ==========================================
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* PUBLIC: Get all donation types
|
|
19
|
+
* ✅ ONLY method actually used by framework
|
|
20
|
+
*/
|
|
21
|
+
async getAllDonationTypes(): Promise<DonationTypeDTO[]> {
|
|
22
|
+
return this.apiClient.get<DonationTypeDTO[]>('/purchase/donation/type');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @explorins/pers-sdk-donation
|
|
3
|
+
*
|
|
4
|
+
* Platform-agnostic Donation Domain SDK for PERS ecosystem
|
|
5
|
+
* Handles donation type retrieval for purchase flow integration
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// API Layer
|
|
9
|
+
export { DonationApi } from './api/donation-api';
|
|
10
|
+
|
|
11
|
+
// Service Layer
|
|
12
|
+
export { DonationService } from './services/donation-service';
|
|
13
|
+
|
|
14
|
+
// Models & Types - re-export all centralized interfaces
|
|
15
|
+
export * from '../shared/interfaces/pers-shared-lib.interfaces';
|
|
16
|
+
|
|
17
|
+
// Models & Types - imported from centralized interfaces
|
|
18
|
+
|
|
19
|
+
// Factory function for creating donation SDK instance
|
|
20
|
+
import { PersApiClient } from '../core/pers-api-client';
|
|
21
|
+
import { DonationApi } from './api/donation-api';
|
|
22
|
+
import { DonationService } from './services/donation-service';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Create a complete Donation SDK instance
|
|
26
|
+
*
|
|
27
|
+
* @param apiClient - Configured PERS API client
|
|
28
|
+
* @returns Donation SDK with flattened structure for better DX
|
|
29
|
+
*/
|
|
30
|
+
export function createDonationSDK(apiClient: PersApiClient) {
|
|
31
|
+
const donationApi = new DonationApi(apiClient);
|
|
32
|
+
const donationService = new DonationService(donationApi);
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
// Direct access to service methods (primary interface)
|
|
36
|
+
// ✅ FRAMEWORK ALIGNED: Only method actually used by framework
|
|
37
|
+
|
|
38
|
+
// Public methods
|
|
39
|
+
getAllDonationTypes: () => donationService.getAllDonationTypes(),
|
|
40
|
+
|
|
41
|
+
// Advanced access for edge cases
|
|
42
|
+
api: donationApi,
|
|
43
|
+
service: donationService
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type DonationSDK = ReturnType<typeof createDonationSDK>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Donation Domain Models
|
|
3
|
+
*
|
|
4
|
+
* Re-exports from centralized pers-shared interfaces for consistency with backend
|
|
5
|
+
* and to provide a single import source for donation-related types.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Core donation entities from centralized pers-shared interfaces
|
|
9
|
+
export type {
|
|
10
|
+
DonationTypeDTO
|
|
11
|
+
} from '../../shared/interfaces/pers-shared-lib.interfaces';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DonationApi } from '../api/donation-api';
|
|
2
|
+
import { DonationTypeDTO } from '../../shared/interfaces/pers-shared-lib.interfaces';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Platform-Agnostic Donation Service
|
|
6
|
+
*
|
|
7
|
+
* Contains donation business logic and operations that work across platforms.
|
|
8
|
+
* No framework dependencies - pure TypeScript business logic.
|
|
9
|
+
* Matches framework DonationApiService capabilities exactly.
|
|
10
|
+
*/
|
|
11
|
+
export class DonationService {
|
|
12
|
+
constructor(private donationApi: DonationApi) {}
|
|
13
|
+
|
|
14
|
+
// ==========================================
|
|
15
|
+
// PUBLIC OPERATIONS
|
|
16
|
+
// ==========================================
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* PUBLIC: Get all donation types
|
|
20
|
+
* ✅ ONLY method actually used by framework
|
|
21
|
+
*/
|
|
22
|
+
async getAllDonationTypes(): Promise<DonationTypeDTO[]> {
|
|
23
|
+
return this.donationApi.getAllDonationTypes();
|
|
24
|
+
}
|
|
25
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -5,11 +5,50 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
// Re-export everything from core
|
|
8
|
-
export * from './core
|
|
8
|
+
export * from './core'
|
|
9
9
|
|
|
10
10
|
// Re-export everything from business domain
|
|
11
11
|
export * from './business';
|
|
12
12
|
|
|
13
|
+
// Re-export everything from transaction domain
|
|
14
|
+
export * from './transaction';
|
|
15
|
+
|
|
16
|
+
// Re-export everything from analytics domain
|
|
17
|
+
export * from './analytics';
|
|
18
|
+
|
|
19
|
+
// Re-export everything from auth-admin domain
|
|
20
|
+
export * from './auth-admin';
|
|
21
|
+
|
|
22
|
+
// Re-export everything from campaign domain
|
|
23
|
+
export * from './campaign';
|
|
24
|
+
|
|
25
|
+
// Re-export everything from donation domain
|
|
26
|
+
export * from './donation';
|
|
27
|
+
|
|
28
|
+
// Re-export everything from analytics domain
|
|
29
|
+
export * from './payment';
|
|
30
|
+
|
|
31
|
+
// Re-export everything from analytics domain
|
|
32
|
+
export * from './redemption';
|
|
33
|
+
|
|
34
|
+
// Re-export everything from analytics domain
|
|
35
|
+
export * from './tenant';
|
|
36
|
+
|
|
37
|
+
// Re-export everything from analytics domain
|
|
38
|
+
export * from './token';
|
|
39
|
+
|
|
40
|
+
// Re-export everything from user domain
|
|
41
|
+
export * from './user';
|
|
42
|
+
|
|
43
|
+
// Re-export everything from user-status domain
|
|
44
|
+
export * from './user-status';
|
|
45
|
+
|
|
46
|
+
// Re-export everything from web3-chain domain
|
|
47
|
+
export * from './web3-chain';
|
|
48
|
+
|
|
49
|
+
// Re-export everything from web3 domain
|
|
50
|
+
export * from './web3';
|
|
51
|
+
|
|
13
52
|
// NOTE: Angular integration available in separate package '@explorins/pers-sdk-angular'
|
|
14
53
|
// Future domains will be added here
|
|
15
54
|
// export * from './campaign';
|